L19. 이 프로그램은 몇 밀리세컨드 후에 종료되는가
우선 프로그램 실행을 실행하니 아래와 같은 창이 출력되고 얼마 후 자동으로 종료되었다.
Ollydbg에서 프로그램을 확인하려 했으나 평소 보이던 모습과 달라 PEiD로 확인하니 UPX로 패킹되어 있다는 것을 알 수 있었다. 이에 언패킹을 하고 다시 Ollydbg에서 실행해보았다.
프로그램을 언패킹한 후 Ollydbg에서 프로그램을 실행하려고 하니 제대로 실행할 수가 없었다.
이에 IsDebuggerPresent를 우회하기 위해 해당 함수를 TEST에서 CMP로 변경하고 실행하였다.
디버거를 우회한 후, Search for > All intermodular calls를 통해 호출되는 모든 API 함수를 살펴보던 중, timeGetTime이라는 함수를 발견하였다.
시간과 관련있는 함수라고 짐작하여 해당 함수가 어떤 기능을 하는 함수인지 찾아보았다.
timeGetTime 함수는 시스템 시간을 밀리 초 단위로 검색하는 함수로, 반환 값은 시스템 시간을 밀리 초 단위로 반환하는 함수라는 것을 알게되었다. 위의 timeGetTime 함수에서 다른 명령문들과 달리 CALL EDI라는 구문이 존재하여 해당 함수에 BP를 걸고 내부로 들어가보았다.
코드를 한 줄씩 실행하다가 00444D38에서 00444D3D가 반복되는 것을 확인할 수 있다. CMP 값에 따라 jump가 결정되는데, 비교되는 값은 00002B70이었다. 16진수 00002B70은 10진수로 11,120이었다.
11,120ms가 되지 않으면 11,120ms가 될 때까지 해당 구간을 반복하는 것이라 예상하고 정답을 제출하였다.
L20. 이 프로그램은 Key파일을 필요로 하는 프로그램이다.
'Cracked by: CodeEngn!' 문구가 출력 되도록 하려면 crackme3.key 파일안의 데이터는 무엇이 되어야 하는가
Ex) 41424344454647
(정답이 여러개 있는 문제로 인증시 맞지 않다고 나올 경우 Contact로 연락주시면 확인 해드리겠습니다)
아무것도 출력되지 않는 상황인데 Cracked by: CodeEngn! 문구가 출력되도록 하는 문제.
패킹되어 있지 않음.
CRACKME3.KEY 파일을 생성하는 명령어가 보이고 파일 사이즈는 18이다. 따라서 CRACKME3.KEY 파일을 생성하고 18바이트 만큼 채워준다.
CRACKME3.KEY 파일 생성. 18바이트 문자열 입력.
생성 후 실행 결과 ReadFile 명령어로 파일을 읽어서 CRACKME3.KEY 파일에 값을 읽어 오는 것을 볼 수 있다
F8로 한 줄씩 실행하다 보면 4020F9 의 4바이트 값과 0x12345678과 xor을 거치면서 키 값이 바뀌는 것을 볼 수 있다. 그런데 마지막 4바이트 6789는 변하지 않은 것을 확인. 401311 위치에 들어가 보았다.
ESI 값 중 1바이트를 AL에 넣는다. 그리고 BL과 AL를 XOR 시킨다. 이렇게 xor 시킨 AL의 값을 ESI의 1바이트에 넣는다. 그리고 ESI와 BL을 각각 1씩 증가 시킨다. 그리고 4020F9의 값과 EAX 값을 더한다. 0과 AL을 비교시키고 같으면 00401335 위치고 점프. CL을 1 증가시킨다. 4F와 BL 비교하고 같지 않으면 40131B 위치로 점프. 반복문이 종료되면 ECXfmf 402149의 값을 넣고 함수 종료한다. 즉 BL을 증가시키면서 CRACKME3.KEY 의 키 값을 한글자씩 읽어와 XOR 연산을 한다.
- key 값이 들어 있는 ESP+4를 ESI에 입력한다. 그 다음 BL을 0x41로 초기화
- key 파일의 내용을 가진 주소를 ESI에 복사. EBX가 가진 주소에서 1byte 31을 넣는다.
- 임의로 입력했던 값 첫번째 바이트 '31' 과 '41'을 xor 한다.
- ESI와 BL 값을 1씩 증가시키고 4020F9 값에 암호화 시킨 값 EAX를 넣는다.
- 암호화된 AL이 0이면 함수는 끝이나고 CL은 1씩 증가시키고 몇번 반복했는지 카운트 한다. (- 키 값을 AL에 저장하여 BL과 xor 연산 후 AL에 저장 시킨 후 AL이 아니면 다시 반복하여 xor을 진행한다.)
- 41(A) ~ 4F(0) 반복하면서 진행. 실제로 입력한 키 값과 xor을 하여 암호화 한다. 이렇게 암호화 된 값은 4020F9에는 암호화된 값에 총 합이 저장되게 된다. (4F 도달할 때까지 반복하므로 최대 14번 반복)
4020F9의 값과 12345678 값과 xor 하고 0040133C 함수를 호출하는 것을 확인.
함수 내부로 이동해서 살펴보니 암호화하고 남은 문자열 즉 15번째에서 18번째 위치의 글자들을 가져온다,
40133C 함수 결과가 EAX로 들어가고 1~14번째 문자를 암호화한 것과 비교.
4020F9의 값을 확인해 보면 1234502F이고 EAX 값을 보면 39383736 이고 이 16진수로 아스키 코드로 변환하면 6789임을 알 수 있어 키 입력 값에 마지막 4글자를 가지고 오는 것을 알 수 있다. 이 마지막 4글자를 1234502F로 바꿔준다..
변경하고 실행한 결과 메시지 창이 뜨긴 하지만 Code Engn!이란 문구 대신 변조된 값이 출력되는 것을 확인. (어떤 값을 작성하든 뒤의 '!'가 나오는 것을 알 수 있다)
메모장에 'CodeEngn1111111111'을 넣고 다시 실행('!'는 자동적으로 붙여진다는 것을 확인하여 따로 붙이지 않았다.) CodeEngn 16진수 값으로 바꾸면 43 6F 64 65 45 6E 67 6E 이다.
키 값과 41 부터 xor 한 값이 43 6F 64 65 45 6E 67 6E 가 나오게 된다. 예를 들어 a xor b는 c이면 a xor c 는 b가 나오기 때문에 41부터 CodeEngn 16진수 값 차례대로 xor 하면 키 값이 출력 될 것이다.
하나씩 계산기를 이용하여 xor 한 결과 02 2D 27 21 00 28 20 26 이 나온다.
Hex-editor를 이용하여 수정했다.
그런데 여기서 앞서 말했던 거와 같이 AL이 0이 아니면 계속 반복하기 때문에 우리가 필요한 CodeEngn을 출력하기 위해서는 이 8 글자 다음에 AL을 0으로 만들어야 한다. 즉 AL과 BL을 xor해서 0이 나와야 한다는 의미로 AL과 BL 값이 같아야 한다. 이 때 BL 값은 49이므로 AL도 49가 된다. Hex editor를 이용해서 수정했다.
수정 후 실행 시킨 결과 4020F9에서 입력 값 뒤에 4자리 수가 7B 55 34 12 인 것을 알 수 있다.
성공! 이것을 보아 중간 9부터 14자리까지의 값은 어떤 값이 나오든 상관이 없다는 것을 알 수 있었다.
참고
https://hackchang.tistory.com/22, https://jeonyoungsin.tistory.com/307
https://hackingboy.tistory.com/57
'2. Reversing (리버싱) > 1) Write UP' 카테고리의 다른 글
[2021.03.13] CodeEngn Basic L01-L04 (0) | 2021.03.13 |
---|---|
[2020.11.28] Reversing.kr Challenge Music Player 라이트업 (0) | 2020.11.28 |
[2020.11.14]CodeEngn Challenges Basic RCE L17, L18 라이트업 (0) | 2020.11.14 |
[2020.11.07]CodeEngn Challenges Basic RCE L13 ~ L16 라이트업 (0) | 2020.11.07 |
[2020.10.10]CodeEngn Challenges Basic RCE L09 ~ L12 라이트업 (0) | 2020.10.10 |