Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 2021
- 강의
- 드림핵
- 해킹캠프
- 라이트 업
- web
- 라이트업
- 히공
- write-up
- ShaktiCTF
- 풀이
- 파이썬
- 리버싱
- 뭉뭉
- 코드엔진
- ctf
- hackingcamp
- vsCode
- 라업
- PYTHON
- 변수
- 워 게임
- Basic
- 리버스 엔지니어링
- write up
- c언어
- probgame
- reversing.kr
- reversing
- 시탭
Archives
히공
HackPack CTF 2021 - Function Pointer Fun 본문
728x90
문제
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
bool changed; // [rsp+13h] [rbp-1Dh]
int i; // [rsp+14h] [rbp-1Ch]
int (*fp)(void); // [rsp+18h] [rbp-18h]
char seed[5]; // [rsp+23h] [rbp-Dh] BYREF
unsigned __int64 v8; // [rsp+28h] [rbp-8h]
v8 = __readfsqword(0x28u);
setvbuf(_bss_start, 0LL, 2, 0LL);
*(_DWORD *)seed = 0;
seed[4] = 0;
printf("Hello, Mr. Eusk. \nPassword > ");
__isoc99_scanf("%4s", seed);
changed = 0;
for ( i = 0; i <= 3; ++i )
{
if ( seed[i] )
changed = 1;
}
if ( !changed )
{
puts("You gotta give an input!");
result = 1;
}
else
{
fp = pickFunction(seed);
((void (__fastcall *)(char *))fp)(seed);
result = 0;
}
return result;
}
메인 함수
seed는 총 4글자까지 입력받는다.
for ( i = 0; i <= 3; ++i )
{
if ( seed[i] )
changed = 1;
}
if ( !changed )
{
puts("You gotta give an input!");
result = 1;
}
이 부분은 null 바이트가 들어갔는지 체크 하는 루틴 이다.
else
{
fp = pickFunction(seed);
((void (__fastcall *)(char *))fp)(seed);
result = 0;
}
이 부분은 널 바이트가 들어있지 않다면 실행하는 루틴이다.
int (*__cdecl pickFunction(char *seed))(void)
{
char res; // [rsp+1Fh] [rbp-31h]
res = (seed[2] | seed[3]) & (*seed | seed[1]);
if ( res == 0x49 )
return funTwo;
if ( res > 0 && res <= 31 )
return funOne;
if ( res > 31 && res <= 63 )
return funThree;
if ( res <= 63 || res > 95 )
return funFive;
return funFour;
}
pickFunction 함수다.
int __cdecl funTwo()
{
FILE *fp; // [rsp+8h] [rbp-38h]
char flag[25]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v3; // [rsp+38h] [rbp-8h]
v3 = __readfsqword(0x28u);
fp = fopen("flag", "r");
fgets(flag, 25, fp);
puts(flag);
return 1;
}
funTwo 함수를 보니 flag라는 이름의 파일을 읽어와서 출력하는 걸 알 수 있다.
나머지 funOne같은 함수는 그냥 문자열만 출력하는 함수였다.
from z3 import *
seed0 = BitVec('seed0', 8)
seed1 = BitVec('seed1', 8)
seed2 = BitVec('seed2', 8)
seed3 = BitVec('seed3', 8)
s = Solver()
s.add(seed0 != 0)
s.add(seed1 != 0)
s.add(seed2 != 0)
s.add(seed3 != 0)
s.add(seed0 != 0x20) # 띄어쓰기
s.add(seed1 != 0x20)
s.add(seed2 != 0x20)
s.add(seed3 != 0x20)
s.add(seed0 != 10) # \n
s.add(seed1 != 10)
s.add(seed2 != 10)
s.add(seed3 != 10)
s.add(seed0 != 9) # \t
s.add(seed1 != 9)
s.add(seed2 != 9)
s.add(seed3 != 9)
s.add((seed2 | seed3) & (seed0 | seed1) == 0x49)
print(s.check())
m = s.model() # [seed3 = 32, seed2 = 73, seed1 = 128, seed0 = 73]
print(m)
input_bytes = bytearray()
for d in m.decls():
input_bytes.append(int(str(m[d])))
input_bytes = input_bytes[::-1]
with open("input_bytes", 'wb') as f:
f.write(input_bytes)
z3를 이용해서 입력해야하는 문자열을 구한 뒤 input_bytes라는 파일에 저장했다.
먼저 로컬에서 실행하기 위해 flag라는 파일을 만들고
FLAG{123}을 입력했다.
정상작동 하는걸 알 수 있다.
플래그 : flag{c1RcU1t5_R_fUn!2!}
'write up > HackPack CTF 2021' 카테고리의 다른 글
HackPack CTF 2021 - "N"ot "G"am"I"ng a"N"ymore in "X"mas (0) | 2021.04.18 |
---|---|
HackPack CTF 2021 - BF means best friend, right? (0) | 2021.04.18 |
Comments