본문 바로가기

Study/Reverse Engineering

dreamhack : rev-basic-3 write-up

728x90

⭐실습을 통해 개념 정리하기⭐

https://dreamhack.io/wargame/challenges/17

 

rev-basic-3

Reversing Basic Challenge #3 이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출

dreamhack.io

 

step1. main함수 분석

 

  1. char형 배열 v4에 256개의 원소가 들어갈 수 있는 공간을 스택에 할당
  2. memset(v4, 0, sizeof(v4));를 사용해 v4의 256바이트를 0으로 설정
  3. "Input: "을 출력 후, v4에 256바이트의 문자열을 사용자에게 입력받아서 저장함
  4. sub_140001000함수에 v4를 인자로 주어, 반환값이 True이면 "Correct"출력

step2. main 내부 함수 분석

sub_140001000함수

for문을 0x18 = 24회 반복하면서 if문의 결과 체크

if문의 조건 성립하면 0i64 반환, 성립하지 않고 24회 for문을 전부 순회완료하면 1i64 반환.

(0i64는 64비트의 정수 자료형에서 0을 의미, 1i64는 64비트의 정수 자료형에서 1을 의미)

 

main함수의 if문을 살펴보면 unsigned int로 형변환해준 후, if문에 들어가있는 것을 확인.

하지만, True / False 여부는 영향X

bool로 형변환되었을떄 True가 되기 위해서는 1i64가 반환되어야함

따라서 sub_140001000함수에서의 if문은 조건 성립되지 않아야함. 

 

byte_140003000[i] != (i ^ *(unsigned __int8 *)(a1 + i)) + 2 * i)이 성립하지 않기 위해서는

0 ~ 23의 값을 가지는 i에 대하여 24회 동안 (i ^ *(unsigned __int8 *)(a1 + i)) + 2 * i) 

연산한 결과가 byte_140003000[i]와 동일해야함.

 

byte_140003000[i]는 데이터 영역에 저장되어 있는 배열이기 때문에 배열 정보를 불러와서 역연산 진행해야함

 

step3. byte_140003000배열 정보 불러오기

byte_140003000 이중클릭하면 그 주소로 이동하게 되고

위와 같이 배열정보가 나오게됨

 

byte_140004000을 선택한 상태에서 shift+E 누르면 해당 데이터를 해석 가능하기 간편한 형태로 익스포트 가능

hex string(spaced)를 사용하여 익스포트한 후, 

python3의 bytes.fromhex 함수를 사용하여 byte 형태로 다시 불러오기 

 

역연산

24바이트의 사용자의 입력값이 a1일 때,

(i ^ *(unsigned __int8 *)(a1 + i)) + 2 * i)의 결과가 익스포트한 24바이트의 데이터와 일치해야함.

 

이때, *(unsigned __int8 *)(a1 + i) a1 배열의 맨 앞 주소에 unsigned __int8 * 형으로 i 만큼의 인덱스만큼을 더하여 다시 맨 앞의 *를 통해 해당 주소의 바이트를 가져옴.( a1[i]로 해석 가능)

 

주의 > 양변의 데이터 모두 8비트 정수이기 때문에, Python에서 역연산 코드를 작성할때는 오버플로우 고려!! 256으로 나눈 나머지를 저장해야함!!!

따라서 i ^ a1[i] == data[i] - 2 * i의 식이 나오게 되고, 양변을 i로 XOR 연산

 

data = bytes.fromhex("49 60 67 74 63 67 42 66 80 78 69 69 7B 99 6D 88 68 94 9F 8D 4D A5 9D 45 00 00 00 00 00 00 00 00")
data = data[:24]

result = []

for i in range(24):
    # i ^ a1[i] + 2 * i == data[i]
    tmp = data[i] - 2 * i
    tmp = tmp % 256

    # i ^ a1[i] = tmp
    a1_i = tmp ^ i

    result.append(a1_i)

result = bytes(result)

print(result)

 

아나콘다 프롬프트에서 실행하면?

 

플래그나옴!

 

'Study > Reverse Engineering' 카테고리의 다른 글

dreamhack : rev-basic-2 write-up  (0) 2024.05.15
dreamhack : simple-operation write-up  (0) 2024.05.13
dreamhack : patch write-up  (0) 2024.05.11
dreamhack : rev-basic-1 write-up  (0) 2024.05.03
Windows Memory Layout  (0) 2024.05.02