일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- PEImage
- dotPeek
- 리버싱핵심원리
- DebugBlocker
- 안티디버깅
- hxd
- Static안티디버깅
- CodeEngn
- Python
- RedLine Stealer
- Dynamic안티디버깅
- JIT
- IL코드
- ImageSwitching
- 서비스디버깅
- 분석 보고서
- UTF-16
- x32dbg
- Self-Creation
- 서비스프로세스
- OllyDbg
- Advanced안티디버깅
- .net
- UTF-32
- PEImageSwitching
- CP949
- Exe2Aut
- 리버싱
- 디버깅
- Visual Studio
- Today
- Total
-榮-
[CodeEngn] Advance RCE L03 Serial 생성 분석 본문
[※참고]
이 글은 CodeEngn Advance RCE L03의 Serial 생성 부분을 분석한 글로 CodeEngn Advance RCE L03 풀이의 일부분입니다.
CodeEngn Advance RCE L03은 CodeEngn Advance RCE L03 을 참고해 주세요.
● CodeEngn Advance RCE L03 풀이 中 Serial 생성
Serial 생성 함수(00401277)는 함수 3개를 반복하면서 입력받은 Name을 사용하여 Serial을 생성합니다.
①
[403258]에 입력받은 Name("CodeEngn")을 옮기고, stack에 0을 넣고 00401142 CALL 00401277 함수 내부로 들어갑니다.
[그림 3]은 CALL 00401277 내부입니다. 처음 00401277로 들어오면 [403000]에는 00000000이 들어있습니다.
00401277의 시작 코드는 [403000] = ([403000] ^ 0AAAh) - 7F9h로 시작됩니다.
XOR과 SUB 명령어가 끝나면 3개의 반복문이 나옵니다.
3개의 반복문을 실행하면 00401328 CMP [EBP+8], 0 코드가 있습니다. 이 코드는 CALL 00401277이 처음 시작되었는지를 판단하는 비교문입니다.
설명을 하면, CALL 00401277은 입력받은 Name의 두 문자를 암호화하여 Name이 끝날 때까지 반복됩니다. 이때, 두 문자의 반복은 특정 조건을 만족하면 종료됩니다. 종료된 뒤 Name이 끝이 났는지 확인을 하고 끝이 아니면 00401277을 호출하는데, 호출 전에 push 0을 합니다.
즉, 다음 문자를 가져오는 코드로 가는 분기 조건이 00401328 CMP [EBP+8], 0입니다. CALL 00401277을 다시 시작하게 되면 호출 전의 push 0 이 [EBP+8]에 위치하게 됩니다.
[EBP+8]에 0이 들어있으므로 입력받은 Name의 두 문자를 암호화하여 CALL 00401241에서 반복합니다.
◎ [00401333 ~ 0040134E] 내부 흐름
[00401333 ~ 0040134E] 내부 흐름 설명 |
설명 및 예시 |
1. ebx = [eax] |
1. eax는 입력받은 Name의 주소를 가지고 있습니다. |
②
00401241의 내부는 [그림 6]과 같습니다. 앞에서 두 문자의 반복은 특정 조건을 만족하면 종료된다고 하였는데, 그 특정 조건이 00401241에 있습니다.
입력받은 암호화된 두 문자로 CALL 004011D5를 반복하면서 CMP [EBP+C], 0을 만족하면 두 문자에 대한 암호화 반복이 종료됩니다.
첫 00401241은 입력받은 암호화된 'C'와 'o'를 가지고 실행됩니다. [EBP+8]에 암호화된 'C'가 있고, [EBP+C]에는 암호화된 'o'가 있습니다.
③
[그림 7]은 004011D5의 내부입니다. 이 곳 코드는 입력받은 파라미터를 사용하여 암호화합니다.
[그림 7]의 붉은 칸이 표의 5.에서 설명한 반환 주소를 00401277로 변환하는 부분입니다.
004011D5 부분은 코드 중간에 바뀌여 CALL 004011D5가 호출될 때마다 같은 코드를 반복하는 것은 아닙니다.
◎ CALL 004011D5 내부 코드 흐름
CALL 004011D5 내부 코드 흐름 [004011E4 ~ ] 설명 |
|
eax = [ebp+8] |
|
① |
② |
③ |
④ |
[403000] = eax |
CALL 004011D5 반복동안의 코드 | ||||||||
1회차 | 2회차 | 3회차 | 4회차 | 5회차 | 6회차 | 7회차 | 8회차 | ... |
①, ③ | ①, ③ | ②, ④ | ①, ③ | ①, ④ | ①, ③ | ②, ④ | ①, ③ | ... |
④
①에서의 설명과 같이 00401277은 [403000] = ([403000] ^ 0AAAh) - 7F9h로 시작됩니다.
반복문 3개를 실행한 뒤 00401328 CMP [EBP+8], 0의 결과가 바뀝니다. ①에서 이 명령어는 CALL 00401277이 처음 시작되었는지를 판단하는 비교문이라 설명했습니다. 따라서 ①에서 Name의 두 문자('C', 'o') 반복 중에는 [EBP+8]에 0이 들어있지 않으므로 JMP 00401380가 실행됩니다.
⑤, ⑥
00401277이 끝나면 00401241로 돌아옵니다.
00401241의 CALL 004011D5 이후 표의 4.부터 시작되어 10.의 재귀 함수로 1.부터 다시 시작됩니다. 그리고 3.의 조건이 맞으면 함수가 종료됩니다.
00401241의 코드와 내부 흐름을 살펴보겠습니다.
◎ 00401241 내부 흐름
00401241 내부 흐름 설명 |
설명 및 예시 |
1. eax = [ebp+8] |
1. 반복 중 : 나누는 값(8.에서의 [ebp+C])을 가진다. |
⑦
⑤,⑥ 표의 3.에서 종료되면 되었을 때입니다. 표의 10.에서 부른 만큼 반환하고 00401277의 CALL 00401241의 이후로 돌아갑니다.
0040135B에서 암호화된 'C'와 'o'으로 만들어진 [403000]의 값과 00401241에서의 마지막 나누는 값과 XOR 합니다.
그리고 다음 문자가 null인자 확인(CMP [EAX], 0 / [그림 13]에서 다음 문자는 'd')한 뒤, null이 아니면 push 0을 하고 00401277을 호출합니다. 이러면 ①의 00401277이 호출되는 부분부터 반복됩니다.
00401377 push 0으로 CMP [EBP+8], 0가 참이 되어 00401277이 처음 시작인 것으로 판단합니다.
따라서 [그림 5]에서 설명한 입력받은 Name의 두 문자를 암호화하여 CALL 00401241에서 반복이 다시 진행됩니다.
('C'와 'o' 이후는 'd'와 'e'가 아닌 'o'와 'd'를 가져옵니다.)
CALL 00401277 반복동안의 두 문자 | ||||||
1회차 | 2회차 | 3회차 | 4회차 | 5회차 | 6회차 | 7회차 (끝) |
'C', 'o' | 'o', 'd' | 'd', 'e' | 'e', 'E' | 'E', 'n' | 'n', 'g' | 'g', 'n' |
◎ 입력받은 Name 문자열 반복 종료
입력받은 Name 문자열의 반복 7회가 모두 완료되면 함수들이 반환됩니다.
Name을 사용한 암호화가 완료된 문자열을 확인할 수 있습니다. (C2A776FAh)
이 문자열을 wsprintfA 함수를 이용하여 %u 형식(부호 없는 10진수)으로 00403284에 복사하면 00403284의 값이 CodeEngn Advance RCE L03의 답입니다. (3265754874d)
'CodeEngn > Advance' 카테고리의 다른 글
[CodeEngn] Advance RCE L05 (0) | 2021.04.02 |
---|---|
[CodeEngn] Advance RCE L04 Serial 생성 분석 (0) | 2021.04.02 |
[CodeEngn] Advance RCE L04 (0) | 2021.04.02 |
[CodeEngn] Advance RCE L03 (0) | 2021.03.31 |
[CodeEngn] Advance RCE L01 (0) | 2021.03.31 |