Correct를 출력하면 되는 문제로 보인다.
 

1. Analysis

일단 ELF파일이니 gdb로 확인하는 문제가 아닐까?

근데 symbol이 없단다. 힘들것같다. 괜히 심볼없는 gdb로 고통받을 바엔 걍 ida라는 현대문물을 쓰자.

int __cdecl main()
{
  write(1, "Reversing.Kr Easy ELF\n\n", 0x17u);
  sub_8048434();
  if ( sub_8048451() )
    sub_80484F7();
  else
    write(1, "Wrong\n", 6u);
  return 0;
}

디컴파일 코드인데 sub_8048451()함수를 통해 뭔가 Wrong이 아닌쪽으로 출력을 한다. 그렇다면 그 함수를 들어가보면 된다.
 

_BOOL4 sub_8048451()
{
  if ( byte_804A021 != 49 )
    return 0;
  byte_804A020 ^= 0x34u;
  byte_804A022 ^= 0x32u;
  byte_804A023 ^= 0x88u;
  if ( byte_804A024 != 88 )
    return 0;
  if ( byte_804A025 )
    return 0;
  if ( byte_804A022 != 124 )
    return 0;
  if ( byte_804A020 == 120 )
    return byte_804A023 == -35;
  return 0;
}

byte_804A020이 정확히 뭔지는 모르겠지만 아마 입력값의 시작점이라고 생각한다. 그리고 그냥 간단한 xor연산을 반복한다. 뭔가 조건문이 복잡할 때는 그냥 그래프로 보는게 훨씬 더 편하다.
 

overview로 보면 이런데 대충 저 조건을 전부 통과해야 Correct로 갈 수 있다는 것이다.
 

왜 오히려 어셈블리어가 더 편한지는 모르겠지만, 위에서부터 보면
 
[804A021] = 0x31
[804A020] ^ 0x34
[804A022] ^ 0x32
[804A023] ^ 0x88
[804A024] = 0x58
[804A025] = 0
 

[804A022] = 0x7C
[804A020] = 0x78
[804A023] = 0xDD
 

2. Solve

바이트 다 뽑아냈으니 순서에 맞춰서 코드를 작성해보자.

key = ''

key += chr(0x78 ^ 0x34)
key += chr(0x31)
key += chr(0x7C ^ 0x32)
key += chr(0xDD ^ 0x88)
key += chr(0x58)
key += '\0'

print(key)

생각보다 너무 쉬워서 어이가 없네

'Security > Reversing' 카테고리의 다른 글

[Reversing.kr] ImagePrc  (0) 2022.08.31
[Reversing.kr] Music Player  (0) 2022.08.31
[Reversing.kr] Easy Keygen  (0) 2022.08.24
[Reversing.kr] Easy Crack  (0) 2022.08.17
Dreamhack secret message  (0) 2022.08.17

1. Analysis

일단 ReadMe.txt파일이 있다.

ReversingKr KeygenMe


Find the Name when the Serial is 5B134977135E7D13

시리얼이 5B134977135E7D13의 Name을 찾으라고 한다.
 

대충 실행 화면은 이렇다. 결론적으로 Correct라는 단어를 출력하는 Name을 찾으면 되는 문제.
 
바로 x32dbg로 열어보자.

대충 어셈블리가 많은데 어지럽다. 그냥 뭐든 입력해서 차근차근 따라가보자.
 
일단 정확히 무슨 함수가 뭘 하는지 확실히 모른다. 그러나 시리얼을 주고 name을 구하라고 했으니 시리얼에 따라 name이 변하는 구조일 것이다.
 
그렇다면 일단 'abcd'를 name에 입력하고 serial에 'efgh'를 입력하고 bp로 확인해보자.

[esp+10]에 시리얼이 저장되고 그 밑에 '71425374'라는 뭔가가 있다. 느낌상 이게 name을 serial로 변환한 것이긴 한데 일단 그렇다고 생각.
 

실제로 이 파트가 시리얼과 name을 변환한 무언가와를 비교하는 함수로 보인다.
테스트를 위하여 input name을 'abcd', input serial을 '71425374'로 입력 후 실행.

결과 'Correct!'가 출력되었다. 그렇다면 이제 우리는 결과값을 알고있으니 name의 연산식을 찾고 이를 통해 serial을 역산하여 name을 찾으면 된다.
 
입력은 그대로 'abcd'로 한다. 연산을 보면서 '71425374'가 어떤 과정으로 입력되는지를 확인해보려고 한다.

이 부분을 따라가면서 확인한다. 우선 입력된 문자열은 [esp+18]에 저장되어있다. 그리고 edi에 옮겨진다.

00401062 | 83C9 FF                  | or ecx,FFFFFFFF                         |
00401065 | 33C0                     | xor eax,eax                             |
00401067 | 83C4 08                  | add esp,8                               |
0040106A | 33ED                     | xor ebp,ebp                             |
0040106C | 33F6                     | xor esi,esi                             |
0040106E | F2:AE                    | repne scasb                             |
00401070 | F7D1                     | not ecx                                 |
00401072 | 49                       | dec ecx                                 |
00401073 | 85C9                     | test ecx,ecx                            |

이 부분들은 'repne scasb'가 정확히 어떤 코드인지 몰라서 검색을 하면서 알았는데, 아래 링크를 보면 완전히 동일한 식이다. 즉 입력된 문자열의 길이를 구하는 코드다. 근데 자세히 보니 같은 문제구나..
https://k4keye.tistory.com/29

[리버싱] 문자열 컨트롤 (repne ,scas)

CTF 문제를 푸는 도중 재미난 문자열컨트롤을 발견하였다. ​ 단순한 시리얼값을 찾아내는 문제였는데 시리얼값을 'ABCDEFG' 로 입력한후 비교하는 루팅을 찾는과정중에 ​ 이러한 repne scasb 명령을

k4keye.tistory.com

코드 실행 결과 [ecx]와 [edx]에는 문자열의 길이 4가 저장됐다.
 

이 반복문이 name을 통해 serial을 만드는 식으로 보인다. 

[esp+esi+C]를 확인했을 때 0x10, 0x20, 0x30이 저장되어있는데 esi는 총 0, 1, 2가 반복되니 이 세 숫자를 사용하는 것 같다. 또한 그 밑 [esp+ebp+10]은 input name이다.
 

반복문 한바퀴를 돌았을 때 ecx에는 71이 저장되었다. 사실 따라가려고 했는데 코드가 너무 복잡해서 그냥 포기했고, 언제 7과 1이 찍히는 지만 찾으면 되는거다. 최종적으로 a가 71이 되었고, 이는 0x10과 a(0x61)이 xor연산된 값이다.

그렇다면 혹시 0x20과 b(0x62)를 xor연산을 하면 42가 나오는지 확인해보자.

정답이다. 그렇다면 0x30도 동일할테니 이번에는 0x10과 d(0x64)를 xor연산을 했을 때 74가 나오는지만 확인하면 된다.

이걸로 우리는 역산식을 찾을 수 있다. 앞번호부터 두글자씩 순서대로 0x10, 0x20, 0x30을 xor한 값을 chr로 변환시키면 그 값이 우리가 찾는 name이 될 것이다.
 

2. Solve

serial = '5B134977135E7D13'

j = 0
name = ''
for i in range(1, len(serial), 2):
    tmp_hex = serial[i - 1] + serial[i]
    if j == 0:
        name += chr(int(tmp_hex, 16) ^ 0x10)
    elif j == 1:
        name += chr(int(tmp_hex, 16) ^ 0x20)
    elif j == 2:
        name += chr(int(tmp_hex, 16) ^ 0x30)
    
    j += 1
    if j >= 3:
        j = 0

print(name)

 

간단한 문제였다.

'Security > Reversing' 카테고리의 다른 글

[Reversing.kr] Music Player  (0) 2022.08.31
[Reversing.kr] Easy ELF  (0) 2022.08.24
[Reversing.kr] Easy Crack  (0) 2022.08.17
Dreamhack secret message  (0) 2022.08.17
Dreamhack hash-browns  (0) 2022.08.03

+ Recent posts