일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 분석 보고서
- Self-Creation
- DebugBlocker
- CodeEngn
- JIT
- Advanced안티디버깅
- Visual Studio
- 리버싱
- IL코드
- hxd
- dotPeek
- PEImageSwitching
- x32dbg
- Python
- 서비스프로세스
- Dynamic안티디버깅
- 서비스디버깅
- PEImage
- OllyDbg
- UTF-16
- 안티디버깅
- .net
- RedLine Stealer
- Exe2Aut
- ImageSwitching
- CP949
- 디버깅
- 리버싱핵심원리
- Static안티디버깅
- UTF-32
- Today
- Total
-榮-
[CodeEngn] Advance RCE L08 본문
● CodeEngn Advance RCE L08 문제
◎ 파일 실행 화면
◎ 패킹 및 난독화 여부 확인
● CodeEngn Advance RCE L08 풀이
우선, [그림 2]에서 찾은 패치 해야 되는 부분으로 이동합니다. [Search for > All referenced text string]에서 해당 문자열을 찾습니다.
0045BB29의 Please Enter More Chars... 문자열은 CMP EAX, 3의 결과로 출력됩니다. 이 부분을 패치하여 Name이 두 문자일 때, 해당 구문이 안나오도록 만듭니다.
Name은 문제의 힌트에서 두 문자라 하였으니 3이 아닌 2와 비교하도록 패치하였습니다.
[※참고]
패치파일 만드는 법은 CodeEngn Basic RCE L01의 "+α 패치파일 만드는 법"
[Search for > All referenced text string]에서 성공 문자열을 찾아 주소로 이동합니다.
성공 문자열의 주소로 이동하면 분기점이 보입니다. 분기 조건은 0045BBA4의 CALL 00404C3C로 보이며, 실패 시 이동한 0045BBC5에 Timeout(Sleep 함수 파라미터)이 있는 것으로 [그림 2]에서 실패 시 반응이 없었던 것이 생각납니다.
주소를 내리다 보면 CALL 0043A074가 반복되는 것을 볼 수 있습니다.
CALL 0043A074이후에 CMP가 있고, Please Enter More Chars... 와 Please Enter Not More Then 30 Chars... 문자열로 보아 CALL 0043A074는 입력된 문자열을 가져오는 함수이고, CALL 0043A0A4는 문자열을 출력하는 함수로 예상됩니다.
[그림 12] 코드에서 입력된 Name과 Key를 가져와서 길이를 검사한 뒤, 문자열을 가져오는 함수를 두 번 더 호출하는 것을 보면 Name과 Key를 다시 가져오는 것으로 추측됩니다.
Name과 Key를 가져온 뒤 CALL 0045B850에서 입력된 Name으로 Key를 생성하고, CALL 00404C3C에서 생성된 Key와 입력된 Key를 비교하는 것으로 생각됩니다.
[그림 12]에서 CALL 0045B850에서 Name으로 Key를 만든다는 것을 확인할 수 있습니다.
[그림 13]에서 CALL 00404C3C의 파라미터를 보면 Name으로 만들어진 Key와 입력받은 Key를 확인할 수 있습니다.
입력받은 Name으로 Key를 생성하는 CALL 0045B850의 내부를 확인해 봅시다.
CALL 0045B850 내부에는 반복문이 크게 4개가 있습니다.
위 반복문들의 결과는 표와 같습니다.
EDX : AAC1 6C20 | EBP - 10 : 0597 A3EC |
EDI : 7364 640A | EBX : 2769 FC81 |
[그림 12]에서 Name(AB)으로 만들어진 Key("AAC1-597A-6F192DD3-7364-2769")을 봤을 때, 반복문들의 결과의 (0을 제외한) 4자리가 Key 앞과 뒤의 두 단락이 같다는 것을 알 수 있습니다.
CALL 0045B850 내부에서 두 번째 반복문 이후의 CALL 0045B54C에서 Key의 중간 문자열이 만들어지는 것을 추측할 수 있습니다.
Key가 "AAC1-597A-6F192DD3-7364-2769"인 Name을 찾기 위해
첫 번째 반복문을 분석하여 반복문의 결과 값이 "5D88"가 나오는 두 자리를 찾아봅시다.
◎ 첫 번째 반복문 흐름
첫 번째 반복문 흐름 |
설명 및 예시 |
1. eax = Name.length |
1. 입력받은 Name의 문자열을 가져오기 위한 ecx ex. Name : AB 1) [EBP-4] : 입력받은 Name의 주소 ex. 첫 번째 반복 : 입력받은 A의 주소 값 / 두 번째 반복 : 입력받은 B의 주소 값 2) esi : 입력받은 Name을 Byte 단위로 입력 ex. ① esi : 0x41 ('A') / ② esi : 0x42 ('B') 3) 첫 번째 Name의 결과 값을 더해서 계산 ex. ① esi : 41 ; edx : 0 / ② esi : 41 ; edx : FFE3 74F0 4) ex. ① esi : 41 * 772 : 1E3F2 6) ex. ① edx : 1E3F2 * 1E3F2 : 92DB 10C4 7) ex. ① esi : 1E3F2 + 92DB 10C4 : 92DC F4B6 8) ex. ① esi : 92DC F4B6 * 474 : FFF1 BA78 9) ex. ① esi : FFF1 BA78 + FFF1 BA78 : FFE3 74F0 |
반복문의 결과 값이 "5D88"이 나오는 두 자리를 찾는 코드
def First_Loop(name, edx): ## 첫 번째 반복문
esi = name + edx
esi = esi * 0x772
edx = esi
edx = edx * esi
esi = esi + edx
esi = esi * 0x474
esi = esi + esi
edx = esi
return edx
if __name__ == '__main__':
for name1 in range(0x30, 0x7A): ## 숫자 0 부터 z 까지
First_edx = First_Loop(name1, 0)
for name2 in range(0x30, 0x7A):
serial = First_Loop(name2, First_edx)
lenght = len(hex(serial))
if '5d88' == hex(serial)[lenght-8:lenght-4]: ## '5D88'와 일치하는 name 출력
print(chr(name1) + chr(name2))
break
● CodeEngn Advance RCE L08 확인
CodeEngn Advance RCE L08의 답(Name의 MD5) : 7E8B9F5CAB4A8FE24FAD9FE4B7452702입니다.
+α
CodeEngn Advance RCE L08 파일의 코드는 CodeEngn Basic RCE L17 문제와 매우 흡사합니다. (Name의 문자 수 차이)
[※참고]
'CodeEngn > Advance' 카테고리의 다른 글
[CodeEngn] Advance RCE L10 (0) | 2021.04.07 |
---|---|
[CodeEngn] Advance RCE L09 (0) | 2021.04.05 |
[CodeEngn] Advance RCE L07 (0) | 2021.04.04 |
[CodeEngn] Advance RCE L06 (0) | 2021.04.02 |
[CodeEngn] Advance RCE L05 (0) | 2021.04.02 |