Never Stop Running
[CodeEngn] BASIC 15 본문
* 리버싱 공부를 위한 문제풀이로
정답을 찾는 것과는 조금 다를 수 있습니다.
[CodeEngn] BASIC 15
문제 풀이 환경 |
Windows 10 / Intel / x32dbg / HxD |
문제 URL |
BASIC 15번 문제.
문제는 Name이 CodeEngn일 때 Serial값을 구하는 것이다.
실행시키면 이러한 창이 뜬다. 여기에 'CodeEngn'을 넣고 맞는 Serial값을 넣으면 된다.
[다음을 찾기] - [현재 모듈] - [문자열 참조]를 이용하여 'CRACKED'라는 문자열이 움직이는 곳을 찾았다.
분기문에 Break Point를 걸었다. 그리고 그 앞에 함수 호출하기 전에 Break Point를 걸었다.
임의의 값을 넣었다. Name = CodeEngn, Serial = 123456.
함수를 지나고 나니 Name값인 'CodeEngn'이 메모리영역에 잘 들어갔다. 이 문자열의 주소는 EDX에 저장된다.
그 다음 함수를 지나고 나니 Serial값인 '123456'이 메모리에 잘 들어갔다. 이 문자열 값은 EAX에 저장된다.
EAX = 0x1E240 = 123456이다. CMP에서는 EAX와 [0045B844]의 값을 비교하는데 [0045B844]의 주소 내부 값을 보니 60610000이라고 쓰여있다. Intel은 리틀엔디언 방식이기 때문에 원래 값은 00006160이고 이걸 10진수로 바꾸면 24928이다.
Name = CodeEngn, Serial = 24928을 넣으면 성공이다.
추가적으로 시리얼이 어떻게 생성되는지 확인해보겠다.
확인 목적이므로 간단히 Name = abcd, Serial = 1234를 넣고 진행한다.
Name = abcd, Serial = 1234.
내가 입력한 값과 비교하는 값이 들어있는 [0045B844] 주소를 보니 아무것도 안 들어있다.
한번 첫 번째 함수를 F8로 지나가보니 이 주소에 값이 생겨있었다. 따라서 첫 번째 함수에서 Name을 받고, 이걸 이용하여 Serial값을 만들어낸다는 것을 알 수 있다.
그래서 첫 번째 함수로 들어갔다.
처음 두 개의 함수에서는 Name값을 받아오고 그 주소를 [0045B840]에 저장한다.
다음 표와 같은 과정을 거쳐 Serial값을 저장할 위치를 초기화한다.
주소 |
코드 |
분석 |
A2 | XOR EAX, EAX | 같은 값을 XOR 하면 0이 됨 |
A4 | MOV [EBX], EAX | EBX = 0045B844의 주소 안에 EAX값을 넣음 |
[00403A64] 주소의 함수를 지나니 EAX 즉 함수의 리턴 값이 4로 바뀐 것을 알 수 있다. 이것을 통해 이 함수는 Name의 길이를 가져온다는 것을 알 수 있다.
그리고 밑의 루프문을 보면 뭔가 어떤 값이 만들어지는 것을 알 수 있다. 그래서 여기를 분석한다.
참고로 루프문 들어가기 전 ESI 주소 안에 1의 값을 넣는다.
주소 |
코드 |
분석 |
B7 | MOV EDX, [EDI] | EDX = &"abcd"이므로 "abcd"의 주소 값을 EDX에 넣어줌. |
B9 | MOV ECX, [ESI] | [ESI] = 1이므로 ECX = 1 |
BB | MOVZX EDX, [EDX+ECX-1] | 현재 ECX = 1이므로 EDX의 주소 값을 가져오는데 그 주소 1Byte의 값을 가져오므로 'a' 하나를 뜻함. C5에서 ESI값을 증가시키고 B9에서 ECX로 넣어주기 때문에 ECX값이 증가함. 따라서 Name의 값을 하나씩 EDX로 넣어줌. |
C0 | SHL EDX, 3 | 110 0001(0x61) -> 11 0000 1000(0x308) |
C3 | ADD [EBX], EDX | [EBX] = 0, EDX = 0x308 -> [EBX] = 0x308 |
C5 | INC [ESI] | [ESI]++ |
C7 | DEC EAX | EAX-- |
이런식으로 모든 Name의 문자 하나하나를 연산하면 된다.
루프를 다 돌면 [004B844] = 0xC50의 값을 가진다.
그리고 다시 [00403A64] 위치 함수를 호출하여 Name의 길이 값을 가져온다.
그리고 그 가져온 값으로 또 연산을 한다.
주소 |
코드 |
분석 |
D1 | SHL EAX, 3 | 100(0x4) -> 10 0000(0x20) |
D4 | ADD [EBX], EAX | [EBX] = 0xC50 ->0xC70 |
D6 | MOV EAX, [EBX] | EAX = 0xC70 |
D8 | SHL EAX, 2 | 1100 0111 0000(0xC70) -> 0011 0001 1100 0000(0x31C0) |
DB | MOV [EBX], EAX | [EBX] = 0xC70 ->0x31C0 |
DD | XOR EAX, EAX | EAX 초기화 |
[0045B844] = 0x31C0 = 12736 이다. 따라서 Name = abcd의 Serial값은 12736이다.
이렇게 하여 최종적으로 Serial 값을 만드는 방법까지 찾았다.
'Training > Codeengn' 카테고리의 다른 글
[CodeEngn] BASIC 14 (0) | 2018.09.24 |
---|---|
[CodeEngn] BASIC 13 (0) | 2018.09.24 |
[CodeEngn] BASIC 12 (0) | 2018.09.24 |
[CodeEngn] BASIC 10 (0) | 2018.09.24 |
[CodeEngn] BASIC 08 (0) | 2018.09.24 |