[codeengn] basic #014

·2025년 7월 3일

CodeEngn 바로가기


문제

Name이 CodeEngn 일때 Serial을 구하시오 (이 문제는 정답이 여러개 나올 수 있는 문제이며 5개의 숫자로 되어있는 정답을 찾아야함, bruteforce 필요) Ex) 11111


1. 프로그램 실행


프로그램을 실행해보면 두 개의 입력값이 필요함을 확인할 수 있다.


x32dbg에서 실행하면 pushad 명령어를 확인할 수 있다. 앞선 문제들과 마찬가지로 UPX 언패킹 진행한다.


2. 흐름 파악


Search for 기능을 이용해 텍스트를 확인해보면 시리얼 입력 성공, 실패 구문을 바로 확인할 수 있다. 해당 주소로 이동한다.


성공 분기 문자열에서 조금 더 올라가 입력값을 저장하는 부분부터 살펴보자. GetDlgItemTextA 함수를 이용해서 403038 위치에 1번 입력값을, 403138 위치에 2번 입력값을 저장하고 있다.


1번 입력값에 대해 글자수만큼 반복해 연산을 수행하고 ESI 레지스터에 저장한다. 예를 들어, 1번 입력값에 pentest를 입력했을 경우 ESI는 00014B3C이 된다. ─①번 연산결과

다음으로 연산된 1번 입력값(00014B3C)과 2번 입력값을 이용해 연산을 수행해 EAX 레지스터에 저장한다. 2번 입력값에 "asdf"를 입력했을 경우, 00014B3C과 "asdf"를 연산한 결과는 0000DBD2가 된다. ─②번 연산결과

이때, ②번 연산을 수행하는 함수를 살펴보자.

00401383 | 55                       | push ebp                         |
00401384 | 8BEC                     | mov ebp,esp                      |
00401386 | FF75 08                  | push dword ptr ss:[ebp+8]        |
00401389 | E8 A2000000              | call <JMP.&lstrlenA>             |
0040138E | 53                       | push ebx                         |
; 레지스터 백업, 셋업 등 준비과정

0040138F | 33DB                     | xor ebx,ebx                      |
00401391 | 8BC8                     | mov ecx,eax                      |
00401393 | 8B75 08                  | mov esi,dword ptr ss:[ebp+8]     |
00401396 | 51                       | push ecx                         |
00401397 | 33C0                     | xor eax,eax                      |
00401399 | AC                       | lodsb                            |
0040139A | 83E8 30                  | sub eax,30                       |
0040139D | 49                       | dec ecx                          |
0040139E | 74 05                    | je unpacked_14.4013A5            |
; 문자열을 정수로 변환

004013A0 | 6BC0 0A                  | imul eax,eax,A                   |
004013A3 | E2 FB                    | loop unpacked_14.4013A0          |
; 10진수 연산 수행

004013A5 | 03D8                     | add ebx,eax                      |
004013A7 | 59                       | pop ecx                          |
004013A8 | E2 EC                    | loop unpacked_14.401396          |
;

004013AA | 8BC3                     | mov eax,ebx                      |
004013AC | 5B                       | pop ebx                          |
004013AD | C9                       | leave                            |
004013AE | C2 0400                  | ret 4                            |

이 함수는 입력된 문자열에 '0'문자열에 해당하는 아스키 값을 빼고 연산을 수행한다. (e.g. '12345' -> 12345)

이 과정은 숫자 문자열 (e.g. '123')을 정수로 변환하는 과정으로, 두 번째 입력값에 '1234'를 입력했다면 함수 수행 결과로 정수 1234가 16진수로 리턴된다. 나는 알파벳 문자열 'asdf'를 입력했기 때문에 랜덤한 16진수 정수 0000DBD2가 리턴됐다.



cmp eas, esi 구문으로 ①번과 ②번 연산결과를 비교해 값이 일치하는지 확인한다. 즉, "pentest", "asdf"를 입력했을 때 ESI: 00014B3CEAX: 0000DBD2가 일치하는지 확인하고 있다.


즉, 1번 입력값으로 "pentest"를 입력했을 때, 2번 입력값으로 ①번 연산결과인 14b3c를 10진수로 변환한 값 84796 입력하면 성공 구문을 확인할 수 있다.


3. 정답 확인

문제에서 Name(1번 입력값)이 CodeEngn일 때 Serial(2번 입력값)을 구하라고 지시했다.

CodeEngn일 때 ①번 연산결과의 결과가 000129A1이므로, ②번 연산을 수행했을 때 Serial 값이 000129A1이 돼야 한다.


이때 ②번 연산은 숫자 문자열을 입력할 경우 단순히 정수로 변환해주기만 하므로, 16진수 000129A1를 10진수로 변환한 값이 Serial이 된다.

업로드중..


기타

문제에서는 Bruteforce가 필요하다고 했는데 브루트포스 없이 문제를 해결했다🤔❓ 다섯자리 숫자 비밀번호이기 때문에 브루트포스가 가능했다는 의미인가?

코드엔진 깃허브에 가면 다양한 풀이를 확인할 수 있다.

profile
🔥

0개의 댓글