Errata

Hacking: The Art of Exploitation

Errata for Hacking: The Art of Exploitation

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
PDF, Other Digital Version Page xi
1st paragraph

The printed book comes with a live Linux CD with example code as stated in the Preface: "[...] This edition features a bootable LiveCD based on Ubuntu Linux [..]". Also, in the publisher page there are links to example code files and errata/updates.

Your product page should contain (current it does not) links to:
- Download an ISO image of the Live CD
- Example code
- Errata

Alessandro Piovaccari  Nov 14, 2011 
Printed Page 17
First function example on page

I am no expert in C so I could be off. I compiled a program with the function as is on the page and it would continue to loop and finally return x to the caller as -1899959296.

Running the program and placing a printf ("%d\n", x); in the function showed x to reach as high as 199584000.

In the function I am referring to the statement:

for (i=1; i < x; i++)
x *= i;

It is as if the "x" in the for parenthesis was continuously being modified. I declared "int j;" in the function and set it "j = x;" then modified the for label as "(int=1; int<j; i++) and that returned the 120 to the caller.

So perhaps my code is off or is the parenthesis always re-read in a for loop?

My initial program test1.c that returned -1899959296:

#include <stdio.h>

int main()
{
int a=5, b;
b = factorial(a);

printf ("b is %d\n", b);

return 0;
}

int factorial(int x)
{
int i;
for(i=1; i<x; i++)
x *= i;
return x;
}

My program that returned 120

#include <stdio.h>

int main()
{
int a=5, b;
b = factorial(a);

printf ("b is %d\n", b);

return 0;
}

int factorial(int x)
{
int i;
int j;
j = x;

for(i=1; i<j; i++)
x *= i;
return x;
}




Joseph  Aug 27, 2011 
PDF Page 19
Within the code snippet.

Under the "Getting your hands dirty" section, the firstprog.c has a typo, which would not allow the code to be compiled and executed correctly. The code however is corrected within the livecd, and sourcebook documents.

Here is the typo:

firstprog.c
#include<stdio.h>

int main()
{
int i;
for (i=0; i < 10; i++) // Loop 10 times.
{
puts("Hello, world!\n"); // put the string to the output.
}
return 0; // Tell OS the program exited without errors
}


How it should read:

firstprog.c
#include<stdio.h>

int main()
{
int i;
for (i=0; i < 10; i++) // Loop 10 times.
{
printf("Hello, world!\n"); // printf the string to the output.
}
return 0; // Tell OS the program exited without errors
}


Brian Anderson  Apr 25, 2015 
Printed, PDF Page 25
2nd paragraph

2nd paragraph says:

"The EIP register is the Instruction Pointer register, which points to the current instruction the processor is reading. Like a child pointing his finger at each word as he reads, the processor reads each instruction using the EIP register as its finger. Naturally, this register is quite important and will be used a lot while debugging. Currently, it points to a memory address at 0x804838a"

Memory address for the EIP register shown in the example code llocated on page 22 is <0x804837a> and not <0x804838a>

Anonymous  Aug 29, 2020 
Printed, PDF Page 25
2nd paragraph

2nd paragraph says:

"The EIP register is the Instruction Pointer register, which points to the current instruction the processor is reading. Like a child pointing his finger at each word as he reads, the processor reads each instruction using the EIP register as its finger. Naturally, this register is quite important and will be used a lot while debugging. Currently, it points to a memory address at 0x804838a"

Memory address for the EIP register shown in the example code llocated on page 22 is <0x804837a> and not <0x804838a>

Anonymous  Aug 29, 2020 
PDF Page 39
1st paragraph

In this example, an array is initialized and contains a "Hello World!\n\0" string. The author then proceeds to explain that the null byte tells the function to stop reading a string when it is encountered.
Then, we have the following line: " If a null byte is inserted in the fifth element
of the character array, only the characters Hello would be printed by the
printf() function.".
This is actually incorrect. If the null byte was inserted in the fifth element, we would only see Hell, as the fifth element is str[4], and contains 'o'. In order for printf to print Hello, the null byte should be inserted in str[5], which is the sixth element, and not the fifth.

Terry Finkel  Apr 21, 2019 
PDF Page 50
Line 5; input.c program

#include <stdio.h>
#include <string.h>

int main() {
char message[10];
int count, i;
strcpy(message, "Hello, world!");
printf("Repeat how many times? ");
scanf("%d", &count);
for(i=0; i < count; i++)
printf("%3d - %s\n", i, message);
}

In the above code, the char array message is of length 10. When strcpy is used to transfer the string "Hello, world!", message may not be long enough to fit the 14 bytes needed.

Jacob Shin  May 22, 2018 
Printed, PDF Page 94
Line 45 in notesearch.c program

In the 'notesearch.c' program shown on pages 93-95, there is an error on line 45 that reads:
"read(fd, note_buffer, note_length); // read note data"
The problem is that read will not reach the newline character, and will therefore not carry down to the next line properly. One way to fix the error is to change the line to read as:
"read(fd, note_buffer, note_length+1); // read note data"
so that the newline character is read.

Another separate but closely related error I ran into that was within the same 'notesearch.c' program was the lseek command used on line 74:
"lseek(fd, length * -1, SEEK_CUR); // rewind file reading by length bytes"
The SEEK_CUR variable isn't defined in any of the libaries included in the program. To fix this, add unistd.h to your includes at top of page:
"#include <unistd.h>"
Also, to get rid of the warnings about the malloc and fatal commands listed in the 'hacking.h' header file, add this include to 'notesearch.c' as well:
"#include <stdlib.h>"

These fixes will allow the program to work as intended.
Hope this saves someone else some time. :)

Brian Schmoker  Oct 24, 2015 
PDF Page 97
function search_note in the program notesearch.c

The function search_note in the program notesearch.c in the book is an incorrect implementation of string search/pattern matching. For instance it will say the following pattern "aab" is not in the string "aaab" even though it is really present.

Anonymous  Nov 24, 2011 
Printed Page 114
first (only) paragraph

In the Find the Ace game (based on the Monty Hall Problem), you in fact increase your chances of finding the ace from 33% to 66% (not 33% to 50%) by switching your choice. This is a minor error and doesn't affect the point being made in the section.

Anonymous  May 23, 2008 
Printed Page 121-122
2nd paragraph-3rd paragraph

When executing exploit_notesearch.c, I had a "Permission denied" Error, which comes from the "notesearch.c". The /var/notes directory can't be read by the exploit so I had to change its permission in order to run the exploit (using "sudo chmod g+r /var/notes" command).

I don't know if it's a mistake from the book or if I did something wrong (despite the fact that I followed it correctly)

Nayk0  May 21, 2014 
PDF Page 128
illustration

Illustration of the stack lists a "return_value" variable. The variable is called "auth_flag".

Anonymous  Mar 20, 2016 
PDF Page 145
Bolded "Shellcode" portion

The address shown for the envioronmental variable "SHELLCODE" seems to be incorrect, showing 0xbffffd56 instead of 0xbffff8e3

Anonymous  Mar 15, 2014 
Printed, PDF Page 175
2nd and 3rd paragraph

"must be located after the first arbitrary memory address of 0x08049754," the address is actually 0x08049794. In the third paragraph "After that, the next memory address to be written to, 0x08049755," the address is actually 0x08049795.

Anonymous  Sep 13, 2016 
Printed Page 197
First paragraph, second sentence.

This is a very minor mistake.

For context, this is in the OSI Model section.
Here is the error:
"The next later is the data link layer."
The typo is the word "later" which should be "layer".

Kevin Goforth  Jan 04, 2019 
Printed Page 203
3rd example at the beggining

It reads "ntohs (long value) Network-to-Host Short" when it should read "ntohs (short value) Network-to-Host Short"

Anonymous  Aug 24, 2019 
Printed, PDF Page 205
Below 3rd paragraph in sample code

host_addr.sin_addr.s_addr = 0; // Automatically fill with my IP

-- The assigned value should be changed to the macro INADDR_ANY, which will eliminate any errors produced from variation in network interfaces. This error is fixed in the practice machine for the book, but remains unchanged in document form.

Anonymous  Sep 21, 2016 
Printed, PDF Page 205
Below 3rd paragraph in sample code

host_addr.sin_addr.s_addr = 0; // Automatically fill with my IP

-- The assigned value should be changed to the macro INADDR_ANY, which will eliminate any errors produced from variation in network interfaces. This error is fixed in the practice machine for the book, but remains unchanged in document form.

Anonymous  Sep 21, 2016 
Printed Page 237
function decode_ip in decode_sniff.c program

Calling inet_ntoa() with ip_hdr->src_addr as argument, which is unsigned int.

It should be called with a in_addr struct instead.

Create two structures of in_addr type:

struct in_addr src_addr, dest_addr;

And assign their s_addr field to the ip header address needed

src_addr.s_addr = ip_header->src_addr;
dest_addr.saddr = ip_header->dest_addr;

then use them in inet_ntoa instead of the raw unsigned integer:

printf("SRC: %s DEST: %s", inet_ntoa(src_addr), inet_ntoa(dest_addr);

Or simply typecast it's address to struct in_addr * then deference it (ugly but effective)

inet_ntoa(* ( (struct in_addr*) &ip_header->src_addr))

Anonymous  Feb 17, 2015 
PDF Page 237
decode_sniff.c

The errata has errors.

Page 237
Here follows the corrected entire text.
Six former errors have been corrected.




Calling inet_ntoa() with ip_header->ip_src_addr as argument, which is unsigned int.

It should be called with a in_addr struct instead.

Create two structures of in_addr type:

struct in_addr src_addr, dest_addr;

And assign their s_addr field to the ip header address needed

src_addr.s_addr = ip_header->ip_src_addr;
dest_addr.s_addr = ip_header->ip_dest_addr;

then use them in inet_ntoa instead of the raw unsigned integer:

printf("SRC: %s DEST: %s", inet_ntoa(src_addr), inet_ntoa(dest_addr));

Or simply typecast it's address to struct in_addr * then deference it (ugly but effective)

inet_ntoa(* ( (struct in_addr*) &ip_header->src_addr))

donPablo  Jul 20, 2020 
PDF Page 240
In the diagram

Within the attacker system, the second IP (192.168.0.22) should be equal to system B's IP (192.168.0.200). One of those IP must be changed.

Anonymous  Aug 26, 2019 
Printed, PDF Page 290
Last sentence "This instruction jumps execution..."

"forward by 19 (0x13) bytes" should be changed to "forward by 20 (0x14) bytes"

Anonymous  Oct 14, 2016 
Printed, PDF Page 308
bind_shell1.s source, execve() section

There is a small typo in the execve() section of the bind_shell1.s source code:

push ecx ; push 32-bit null terminator to stack

should be

push edx ; push 32-bit null terminator to stack

Because $ecx is not really null, this shellcode will cause segmentation fault when connecting to the socket. edx should be used instead.

iphelix  Mar 24, 2011 
Printed, PDF Page 315
connectback_shell.s source, dup2() section

There is a small typo in the dup2() section of the connectback_shell.s source code:

xchg eax, ebx; Put socket FD in ebx and 0x00000003 in eax.

should be

xchg esi, ebx; Put socket FD in ebx and 0x00000003 in esi.

Because we are using the same socket FD created using socket(), we should restore it from esi instead of eax which is null after successful connect().

iphelix  Mar 24, 2011 
Printed Page 335
Last line - 4

The exploit script “xtool_tinywebd_stealth.sh” is subsequently referred to as “xtool_tinywebd_steath.sh (stealth is missing the l). The program is referenced incorrectly on page 335, 340,345,347,349. Possibly other occurrences.

Emily Bagwell  Mar 06, 2023 
Printed Page 360
Near the end of the page

push BYTE 0x8 should be push BYTE 0x7
String "/bin/sh\x00" consists of 8 characters. The first character is pointed by [ebx+0] and the 8th by [ebx+7]. Consequently, if we push BYTE 0x8 we decode one more chararacter (byte) outside the bounds of the string and may mangle some important data (which does not happen in this case, at least on my vm)

Alexios Voulimeneas  Aug 22, 2015