파일 실행 시 위와 같은 화면을 얻을 수 있고 serial값을 입력 시 잘못된 정보인 거 같으면 꺼지는 점을 발견했다.
올리디버거로 파일을 실행 시 빈칸의 창이 뜬다.
추후 어떤 부분을 지나면 화면에 출력되지 않을까 하는 추측으로 진행해보았다.
먼저 어디서 실행이 되나 찾아보기 위해서 계속 f8을 눌러보았다.
00401481부분에서 프로그램이 걸리는 부분을 확인했다.
F7을 통해 메인함수로 접근했다.
주석 부분에는 내가 좀 낙서를 많이 적어서 어지럽지만 초기화면은 저렇지 않았다.
이 부분을 지나자 ,
화면에 출력되었다. 마찬가지로
이 부분 통과 시
serial이 출력되었다. 하지만 입력은 할 수 없었다.
계속해서 진행해 보았다.
401104 부분을 지날 때 값을 입력해야만 넘어갈 수 있게 화면이 바뀌었다.
아무 값이나 입력 후,
이후 f8을 통해 계속해서 넘어가 보았다.
이 부분에서 success가 뜰 수 있는 조건을 알게 되었는데 , 0040112A에서 EAX값이 0이 되면 SUCCESS로 갈 수 있었다.
여기까지 알아내고 초기화를 해서 입력 부분 함수부터 다시 살펴봤다.
f7을 통해서 내부를 조금 살펴봤다.
특별한 부분은 찾지 못하고, 이 부분이 실제로 실행되는 부분인 것 같았다.
아무 값이나 입력 후 일단 넘어가 보았다.
이후 F8을 통해 진행을 해보면서, 레지스테값을 봤는데 , Arg1의 값에 HackeRs라는 값이 있었고 push eax를 통해 EAX로 들어가는 것을 확인했다 . ESP에는 내가 입력한 값이 들어가 있는 것을 볼 수 있는데, 그 전에 ESP로 넘어갔다고 추측 후 넘어가 보았다.
이 후 처음 만난 함수에서 무작정 F7을 들어가 보았다.
이 함수는 들어가서 무한루프에 빠지는 것을 확인했는데 , 다만 이상한 점은
루프를 돌 때마다 가장 앞에 있는 문구가 대문자는 소문자로 소문자는 대문자로 바뀌면서 사라지는 것이었다.
그렇게 HackErs값이 다 사라지고 나서야 루프를 빠져나와 retn이 되는 것을 확인했다.
이후 F8을 진행 중에 , 내가 입력한 문구(arg2)는 ECX로 왔고, 기존 값인(arg1)은 EDX로 적재되어 있는 것을 확인했다. 다만 아까 그 대소문자를 변경하는 함수를 지나서 인지 , 기존 HackeRs에서 hACKErS로 바뀐 것을 확인했다.
이후 나온 함수에 일단 접근해보았다. (F8)
위 함수의 내용이다.
정리를 해보았는데 ,
arg1과 arg2 두 개 이용 함수
1. ebp레지스터 값을 esp와 동일하게 만든다
2. ecx와 exi 레지스터를 스택에 푸시
3. arg1은 eax로 이동 후 스택으로 푸시 --> 401160 함수에 인수로 전달 결과는 esi
4. arg2은 ecx로 이동 후 스택으로 후시 --> 401160함수에 인수로 전달 결과는 eax
5. 이후 esi와 eax의 값을 비교 같으면 주소 0040105로 점프
6. 0x0040105A에서 함수는 값 0을 [local.1]의 지역 변수로 이동합니다.
7. 그런 다음 주소 0x0040107E로 점프 후 0x0040107E에서 함수는 arg.1의 값을 edx 레지스터로 이동하고 edx를 스택에 푸시하고 주소 0x00401160에서 동일한 함수를 호출 후, 이 호출의 결과는 [local.1]에 있는 지역 변수의 값과 비교.
8. 크거나 같으면 함수는 주소 0x004010 AB로 점프하고 그렇지 않으면 다음 명령어로 계속 진행합니다.
9. 그런 다음 함수는 arg.1의 값을 eax 레지스터로 이동하고 해당 주소에 있는 바이트를 검색합니다. 또한 arg.2에 있는 바이트를 검색하고 해당 값에서 1을 뺍니다.
10. 그런 다음 함수는 이 두 값을 비교하고 같으면 주소 0x004010A9로 이동하고 그렇지 않으면 값 1을 eax 레지스터로 이동하고 주소 0x004010 AD로 이동합니다.
아닐 시 1을 eax로 이동 후 004010 AD이동
마지막으로 함수는 스택에서 esi 및 ebp 레지스터를 팝 하고 ebp가 가리키는 주소로 점프하여 반환한다.
정리해보면 , 401160 함수는 간단하게 말하면 입력값을 자리 수로 바꾸는 것이었다.
예를 들어 arg1은 hACKErS였으니 eax ---> esi로 전달된다. 그럼 esi값은 00000007
arg2는 abcd였으니 ecs ---> eax로 전달된다. 그럼 eax값은 00000004
이후 이 주소를 비교했을 때, 같을 시 0040105로 점프하게 되고 그렇지 않으면 eax값이 00000001로 되면서 함수를 빠져나간다. 이 상태로 함수를 나가게 되면 failed가 나온다. 이유는
함수를 나온 후 부분부터인데 , 00401128 부분 test eax, eax에서 값이 1이면 failed가 출력되는 함수로 나가게 된다.
이런 결과가 안 나오도록 , eax를 맞추기 위해 글자수를 맞춰서 입력해 보았다.
현재 arg2 값 : abcdefg
위 조건을 만족하니 EAX와 ESI의 값이 00000007로 같아진 것을 확인할 수 있다.
이제 5번의 조건을 만족하였으니 ,
0040105A로 접근한 것을 확인할 수 있었다.
일단 계속 접근해 보았다.
7번의 내용처럼 , arg1의 값을 edx레지스터로 이동하고 edx를 스택에 푸시 후, 주소 00401160에서 동일한 함수를 호출한다. 이때 이 호출의 결과를 [local1.1]에 있는 지역 변수의 값과 비교하게 된다.
비교결과가 작을 시
이 쪽으로 들어올 수 있다.
이후 진행을 해보면
이 부분을 통과 시
이렇게 순차적으로 eax와 ecx 값에 arg1과 arg2의 값을 토대로 바이트 값이 쌓이는 것을 확인할 수 있다.
이후 EAX 값에서 1을 빼고
ECX와 EAX의 값을 비교하게 되는데 , 이 비교값이 같아야 004010A9로 진행이 되었다.
만약 값이 틀리게 되면 그대로 이 함수를 빠져나가 failed값으로 유도되는 것을 확인했다.
그래서 혹시 arg2의 값을 arg1과 같게 한다면 되지 않을까 생각해 보고 진행을 했을 때에는 생각해 보니 , 정상적인 방법으로는 마지막에 1을 빼서 절대로 같게 될 수가 없는 구조였다.
그렇다면 왜 arg1과 arg2의 값이 바뀌는지를 추측해야 했고 , 왜 기본값인 hACKErs는 68이 되고 아까 입력한 abcdefg는 61이 되는지 생각을 해봐야 했다. 이때 ASCII "abcdefg"라는 문구를 발견했고, 아스키코드에 뭐가 있나 살펴보기로 했다.
먼저 소문자 a를 봤을 때 16진수로 0x61 임을 봤고, h는 0x68이었다.
소름 돋게도 앞자리에 연관이 있는 것 같았다. 그래서 나는 1이 빠지는 것을 감안해 i로 시작하는 문구를 입력해 보았다.
비교 부분에 정확히 일치했다!
비교 부분을 통과해 004010A9로 접근하게 되었고, 004010A9의 값은 00401063으로 jmp 하는 것이었다. 다시 처음 비교 부분이었다.
이렇게 비교를 해보니 아까와는 다르게 앞자리가 사라진 것을 확인할 수 있었고, 계속 진행했을 때,
61과 41로 변해있었다. arg1과 arg2의 각 앞자리 수의 16진수 값이었다. 역시 61도 1을 빼 나중에는 60과 41을 비교하게 된다.
여기서 이 문제를 풀었다 직감했다.
이 문제를 수없이 풀어보면서 arg1의 값은 "hACKErs"에서 바뀌지 않았다.
그럼 이 문자에서 한 자리씩 더 한 값을 아스키코드로 입력하면 되지 않을까였다.
"iBDLFst" 그렇게 나온 문자였고, 바로 실행해 보았다.
반복 함수에서 아까와는 다르게 자릿수가 줄면서 계속 진행되었고, 뒤에 3자리를 남겨놓고 루프를 탈출했다.
구문을 탈출한 후 success조건인 EAX값이 0으로 되어있는 것을 확인했고, 계속 진행했다
제대로 된 방법으로 드디어 success값을 찾을 수 있었다.
'실습 > [System Hacking 실습]' 카테고리의 다른 글
EasyBOF (0) | 2023.05.01 |
---|---|
HelloBoF (0) | 2023.04.02 |
CrackMe 3번 문제 풀이 (0) | 2023.03.26 |
Crackme 2번 문제 풀이 (0) | 2023.03.17 |
Crackme 1번 문제 (0) | 2023.03.17 |