CTFlearn의 아흔한번째 문제
이번엔 Medium 난이도의 리버싱 문제이다.
뒤로갈수록 뭔가 앞쪽에 있던 문제들이랑 난이도 책정 기준이 다른것 같다.
문제 설명을 읽어보면
checkNum 이 true 를 리턴하게 하는 input 이 뭐냐고 물어본다.
public static boolean checkNum(int);
descriptor: (I)Z
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: iload_0
1: iconst_3
2: ishl
3: istore_1
4: iload_0
5: ldc #2 // int 525024598
7: ixor
8: istore_2
9: iload_1
10: iload_2
11: ixor
12: ldc #3 // int -889275714
14: if_icmpne 21
17: iconst_1
18: goto 22
21: iconst_0
22: ireturn
LineNumberTable:
line 3: 0
line 4: 4
line 5: 9
StackMapTable: number_of_entries = 2
frame_type = 253 /* append */
offset_delta = 21
locals = [ int, int ]
frame_type = 64 /* same_locals_1_stack_item */
stack = [ int ]
이게 문제에서 주어지는 checkNum 의 코든데
생전 처음보는 형태였다.
검색해보니 JAVA Bytecode 였고,
이걸 해석할 수 있는 가이드가 위키피디아에 있었다.
https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
위키피디아를 보면서
이게 맞는건지 계속 스스로를 의심하는 상태로 문제 해결을 시도했는데
얻어걸린건지 플래그를 찾을 수 있었다.
크게 세 부분으로 볼 수 있는데
0: iload_0
1: iconst_3
2: ishl
3: istore_1
이부분은 input 값을
input << 3 하는 부분이다.
4: iload_0
5: ldc #2 // int 525024598
7: ixor
8: istore_2
다음으로 이부분은
input 값을 525024598 과 xor 하는 부분이다.
9: iload_1
10: iload_2
11: ixor
12: ldc #3 // int -889275714
14: if_icmpne 21
마지막으로 여기는
input << 3 과 input ^ 525024598
두 값을 xor 해서
그 값이 -889275714 인지 확인하는 부분이다.
저 숫자가 대체 뭐지 하고 계산기에 써봤는데
0xCAFEBABE 였다.
대충 코드 돌아가는걸 알았으니
파이썬으로 똑같이 구현해주면 된다.
그런데 input 에 들어갈 숫자범위가
32-bit signed integer
즉, -2,147,483,648부터 2,147,483,647까지기 때문에
경우의 수가 너무 많다.
이걸 그냥 for 문 하나로만 돌리면 시간이 엄청나게 오래걸릴것이다.
num = 0x1f4b3d56
flag = 0xcafebabe
for i in range(4294967296):
tmp1 = i <<3
tmp2 = num ^ i
if tmp1 ^ tmp2 == flag:
print(i)
일단 이렇게 의도하는 대로 코드를 대충 짜준 뒤에
ChatGPT 에게 멀티스레드 코드로 바꿔달라고 던져주면 된다.
워게임 풀면서 코드 작성을 고민하지 않으니 너무 편하다.
import threading
num = 0x1f4b3d56
flag = 0xcafebabe
result_lock = threading.Lock()
result_found = False
result_value = None
def search(start, end):
global result_found, result_value
for i in range(start, end):
if result_found:
return
tmp1 = (i << 3) & 0xffffffff
tmp2 = num ^ i
if tmp1 ^ tmp2 == flag:
with result_lock:
result_found = True
result_value = i
return
# 스레드 개수
num_threads = 8
# 범위를 스레드 개수로 분할
step = 4294967296 // num_threads
ranges = [(i * step, (i+1) * step) for i in range(num_threads)]
ranges[-1] = (ranges[-1][0], 4294967296)
# 스레드 생성 및 실행
threads = []
for start, end in ranges:
t = threading.Thread(target=search, args=(start, end))
threads.append(t)
t.start()
# 모든 스레드 종료 대기
for t in threads:
t.join()
# 결과 출력
if result_found:
print("Result: ", result_value)
else:
print("Result not found.")
이렇게 친절하게 주석까지 달아서 코드를 작성해준다.
코드를 실행시키면 이렇게 숫자가 하나 나오는데
이걸 그대로 쓰면 안된다.
32-bit signed integer 범위인 -2,147,483,648부터 2,147,483,647를 넘어가기 때문이다.
이걸 해당 범위 내로 한정시킬려면
-4,294,967,296 를 해주면 된다.
해당 값이 문제의 플래그이다.
'워게임 > CTFlearn' 카테고리의 다른 글
[CTFlearn] Bobby Toe's iPad - 포렌식 / Stegsolve / HxD (76) | 2023.07.12 |
---|---|
[CTFlearn] The Keymaker - 포렌식 / JPEG / HxD (70) | 2023.07.10 |
[CTFlearn] Riyadh - 리버싱 / IDA / Pwndbg (49) | 2023.04.27 |
[CTFlearn] Brute Force is Fun! - 포렌식 / HxD / Python (62) | 2023.04.23 |
[CTFlearn] Skynet Is (Almost) Taking Over - 암호학 / RsaCtfTool (74) | 2023.04.20 |