다운받고 압축을 풀면, Serial = 5B134977135E7D13 인 Name 을 찾으라한다.
Name 과 Serial 을 입력받는걸 볼 수 있다.
32bit EXE 파일이므로, 올리디버거로 연다음, 문자열검색으로 입력받는곳으로 가보자.
0040102E |. 68 60804000 PUSH OFFSET 00408060 ; ASCII "Input Name: "
00401033 |. F3:AB REP STOS DWORD PTR ES:[EDI]
00401035 |. 66:AB STOS WORD PTR ES:[EDI]
00401037 |. AA STOS BYTE PTR ES:[EDI]
00401038 |. C64424 10 10 MOV BYTE PTR SS:[ESP+10],10
0040103D |. C64424 11 20 MOV BYTE PTR SS:[ESP+11],20
00401042 |. C64424 12 30 MOV BYTE PTR SS:[ESP+12],30
00401047 |. E8 6D010000 CALL 004011B9
0040104C |. 83C4 04 ADD ESP,4
0040104F |. 8D4424 10 LEA EAX,[ESP+10]
00401053 |. 50 PUSH EAX ; /Arg2 => OFFSET LOCAL.74
00401054 |. 68 5C804000 PUSH OFFSET 0040805C ; |Arg1 = ASCII "%s"
00401059 |. E8 44010000 CALL 004011A2 ; \Easy_Keygen.004011A2
Name을 입력받는다. buf = ESP+10
00401077 |> /83FE 03 /CMP ESI,3
0040107A |. |7C 02 |JL SHORT 0040107E
0040107C |. |33F6 |XOR ESI,ESI
0040107E |> |0FBE4C34 0C |MOVSX ECX,BYTE PTR SS:[ESI+ESP+0C]
00401083 |. |0FBE542C 10 |MOVSX EDX,BYTE PTR SS:[EBP+ESP+10]
00401088 |. |33CA |XOR ECX,EDX
0040108A |. |8D4424 74 |LEA EAX,[ESP+74]
0040108E |. |51 |PUSH ECX
0040108F |. |50 |PUSH EAX
00401090 |. |8D4C24 7C |LEA ECX,[ESP+7C]
00401094 |. |68 54804000 |PUSH OFFSET 00408054 ; ASCII "%s%02X"
00401099 |. |51 |PUSH ECX
0040109A |. |E8 B1000000 |CALL 00401150
0040109F |. |83C4 10 |ADD ESP,10
004010A2 |. |45 |INC EBP
004010A3 |. |8D7C24 10 |LEA EDI,[ESP+10]
004010A7 |. |83C9 FF |OR ECX,FFFFFFFF
004010AA |. |33C0 |XOR EAX,EAX
004010AC |. |46 |INC ESI
004010AD |. |F2:AE |REPNE SCAS BYTE PTR ES:[EDI]
004010AF |. |F7D1 |NOT ECX
004010B1 |. |49 |DEC ECX
004010B2 |. |3BE9 |CMP EBP,ECX
004010B4 |.^\7C C1 \JL SHORT 00401077
ESP+0C : 0x10,0x20,0x30 이 순서대로 저장되어있다.
Index 0,3,6~~ == 0x10 과 XOR
Index 1,4,7~~ == 0x20 과 XOR
Index 2,5,8~~ == 0x30 과 XOR
XOR 한 값은, 0x401150 함수에 의해, 문자열로 바뀌어 ESP+74 배열에 저장된다.
004010C1 |. 68 44804000 PUSH OFFSET 00408044 ; ASCII "Input Serial: "
004010C6 |. F3:AB REP STOS DWORD PTR ES:[EDI]
004010C8 |. E8 EC000000 CALL 004011B9
004010CD |. 83C4 04 ADD ESP,4
004010D0 |. 8D5424 10 LEA EDX,[ESP+10]
004010D4 |. 52 PUSH EDX ; /Arg2 => OFFSET LOCAL.74
004010D5 |. 68 5C804000 PUSH OFFSET 0040805C ; |Arg1 = ASCII "%s"
004010DA |. E8 C3000000 CALL 004011A2 ; \Easy_Keygen.004011A2
이제 위에서 생성된 Serial 과 비교할 Serial 을 입력받는다.
004010EA |> /8A10 /MOV DL,BYTE PTR DS:[EAX]
004010EC |. |8ACA |MOV CL,DL
004010EE |. |3A16 |CMP DL,BYTE PTR DS:[ESI]
004010F0 |. |75 1C |JNE SHORT 0040110E
004010F2 |. |84C9 |TEST CL,CL
004010F4 |. |74 14 |JZ SHORT 0040110A
004010F6 |. |8A50 01 |MOV DL,BYTE PTR DS:[EAX+1]
004010F9 |. |8ACA |MOV CL,DL
004010FB |. |3A56 01 |CMP DL,BYTE PTR DS:[ESI+1]
004010FE |. |75 0E |JNE SHORT 0040110E
00401100 |. |83C0 02 |ADD EAX,2
00401103 |. |83C6 02 |ADD ESI,2
00401106 |. |84C9 |TEST CL,CL
00401108 |.^\75 E0 \JNZ SHORT 004010EA
2020/03/18 - [Wargame Write-Up/Reversing.kr] - [Reversing.kr] (Reversing) Easy Crack 풀이
저번문제와 비슷한 구조로, 2글자씩 비교한다. 맞으면 Correct 를 출력한다.
시리얼 생성원리를 알았으니,
5B134977135E7D13 이 생성될때 Name 을 구하는 소스를 작성하자
1
2
3
4
5
6
7
8
9
|
ar=[0x10,0x20,0x30]
ar_c=0
serial='5B134977135E7D13'
Name=''
for i in range(0,16,2):
Name+=chr(int(serial[i:i+2],16)^ar[ar_c])
ar_c=(ar_c+1)%3
print(Name)
|
Serial 은 문자열이지만, 16진수가 그대로 저장되는거니까
Name의 길이= len(Serial)/2
두글자씩 가져와서 10,20,30 과 다시 XOR 해서 복호화 할 수 있다.