문제의 답은 OEP를 구한 후 '등록성공' 으로 가는 분기점의 OPCODE를 구하시오. 정답인증은 OEP + OPCODE
패킹의 유무를 확인해보았는데 UPX 패킹이 아니라 ASPack 패킹인것 같다 그래서 ASPack이 무엇인지 검색을 해보니
UPX와 같은 패커이다. 새로운 패커가 나왔는데 계속 자동화 패커만 의존할 수 없으니 패킹의 원리가 어떻게 되는지 알아보기로 했다.
Packing 원리
저번에 9에서도 비슷한것을 보았지만 PUSHAD로 레지스터 값을 스택에 저장하고 나중에 원본코드가 다 복구되면 메모리에 POPAD 명령을 통해서 다시 레지스터 값을 참조하게 될것이다. 그래서 PUSHAD를 수행한후의 ESP 값에 BP를 설정해주면 쉽게 OEP로 분기가 가능하지 않을까 생각을 해보았다.
Break Point
레지스터 상태에서도 볼수있듯이 PUSHAD명령을 수행하고 나서 레지스터의 모든 값을 스택에 넣고 시작한다.
???? : 아무리 찾아도 안나온다 -> 오류가 있는지 확인해보자
에러의 내용을 확인해보니 entry point가 다른곳에 있다고하는데 원인을 분석해보면
1. 패킹이 잘되어 있다.
2. ollydbg가 64bit와 호환이 되지 않는다. -> 둘중에 하나
패킹은 한마디로 실행 압축을 말한다.
일반 압축파일과 차이점은 일반 파일은 zip으로 확장자가 바뀌지만 패킹은 확장자가 바뀌지 않는다.
Search for ->Find All commands
POPAD를 검색해주면 사용된 모든 POPAD가 나오는데 제일먼저 나온 POPAD안으로 들어가 보았다.
BP를 걸고 실행을 해보니 바로 실행이 되버려서 (패킹이 여기서 안풀린거 같음)
다시 두번째 POPAD로 들어가보았다.
POPAD 이후로도 실행을 해보았지만 레지스터 값이 변하지 않았다
아마도 지금보는 POPAD이후로 패킹이 풀린듯 하다.
위에서 볼 수 있지만 실행하기전에는 PUSH 0이었다가 실행을 해보면 00445834라고 뜬다.
계속 실행을 시켜보았다.
return이 나오게 되는데 RETN함수가 실행되면 그 후에 프로그램이 실행된다.
그러면 최근에 적재된 00445834가 OEP 주소인것을 알 수 있다.
그래서 해당 OEP로 이동을 했다.
->Follow immediate constant
그럼 이제 성공메세지 확인을 위해서 text string으로 검색을 해보았다.
well done 이라는 문자열이 성공메세지를 출력해준다는것을 알수있다.
문제에서 말한 OEP는 찾았는데 OPCODE는 무엇인가
컴퓨터 과학에서명령 코드(opcode←operation code, instruction syllable, instruction parcel, opstring[1][2][3][4][5][6][7])는기계어의 일부이며 수행할 명령어를 나타내는 부호를 말한다. -> Wiki pedia
수행할 명령어를 나타내는 부호를 말하는 말한다고 하는데 이 프로그램에서는 조건에 따라서
성공과 실패를 구분하는 지점이 아닌가 생각해보았다.
JNZ SHORT 0044552B이가 OPCODE인것을 볼 수 있는데 JNZ는 조건 점프라서 zero flag
즉, 두개의 값을 비교했을때 값이 같으면 1이고 다르면 0을 반환 해준다 .
하지만 지금은 zero flag가 0을 반환할것이기 때문에 well done이라는 문자열을 출력하지 않고, 점프도 하지않을것이다.
문제에서 디버깅을 감지하는 함수는 무엇인가를 보아 디버깅을 감지한 후에 정상 여부를 출력하는것 같다.
OllyDBG로 열고나서 디버깅을 진행해 보았다.
디버거로 디버깅을 진행해본결과 디버깅을 감지하고 디버깅 당함이라는 문자를 보여준다.
00408454의 주소의 CALL 명령어를 통해서 실행이 된다 Break Point를 걸고 함수 내부로 진입 해보았다.
함수 내부에서 디버깅을 탐지한후 탐지 여부에 따라서 정상과 디버깅당함이라는 문자열을 무한 반복한다.
계속해서 디버깅을 진행해보았다.
0040105E주소에서 KERNEL32.lsDebbugerPresnt 라는 함수이름이 보인다.
IsDebuggerPresent() 함수는 kernel32.dll에 export되는 함수이며 디버깅을 체크하는 MS에서 공식적으로 지원하는 안티리버싱 API이다. 해당 프로세스가 디버깅을 당하고 있는지에 대한 여부를 PEB구조체의 디버깅 상태값을 확인하며 디버깅을 당하고 있다면 1을 아닐 경우 0을 리턴한다.
IsDebuggerPresent() 함수는 내부적으로 TEB(Thread Environment Block)와 PEB(Process Environment Block)을 이용하며 PEB내의 Begin Debugger라는 멤버의 값을 기준으로 유저모드 디버거에 의해 디버깅을 판단한다
- TEB(Thread Enviorment Block) 프로세스에서 실행되는 스레드의 정보를 담고있는 구조체이다
- OS 환경마다 다르다. (Windows7의 경우 Windows XP SP3 보다 확장)
- 시작 주소 : FS:[0x00], FS:[0x18](User mode)
- PEB(Process Enviorment Block) 프로세스의 정보를 담고있는 구조체
- PEB 구조체는 OS마다 달라진다 (Windows7의 경우 Windows XP SP3 보다 확장)