제리의 블로그

PMA Lab15-01.exe 안티디스어셈블리 본문

카테고리 없음

PMA Lab15-01.exe 안티디스어셈블리

j3rrry 2018. 8. 26. 16:30

Lab15-01.exe

Lab15-01.exe 파일을 그냥 더블클릭해보면

커맨드 창이 순식간에 떳다 사라진다.


그래서 아래와같이 실행시켜보았다.

C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_15L>Lab15-01.exe
Son, I am disappoint.

뭔가 조건이 맞지 않은 모양이군요.

문자열이 나왔으니 함 찾아볼까요


.data:00403010 0000000A C Good Job!            
.data:0040301C 00000016 C Son, I am disappoint.

실패 문자열뿐만이 아니라 성공 문자열까지 나온 것을 확인할 수 있습니다.



.text:00401047                 xor     eax, eax
.text:00401049                 jz      short near ptr loc_40104B+1

안티디스어셈블리 기법이 적용되어 있었습니다.

ida 같은 디스어셈블러는 행위기반 디스어셈블링으로 표현을 하는데

jump 를 하지 않은것을 우선으로 신뢰하기 때문에 jz 명령어 그 바로다음을 opcode로 인식하여 번역한 모습입니다.


그러나 xor 명령어는 ZF를 SET 시키는 녀석으로 jz는 선택분기가 아니라 무조건 분기가 되어있습니다.

이 부분을 수동으로 다듬어 줍시다.



.text:0040104C loc_40104C:                             ; CODE XREF: .text:00401049j
.text:0040104C                 push    offset aGoodJob ; "Good Job!"
.text:00401051                 call    ds:printf
...
.text:00401063 loc_401063:                             ; CODE XREF: .text:00401060j
.text:00401063                 push    offset aSonIAmDisappoi ; "Son, I am disappoint."
.text:00401068                 call    ds:printf

그러니 이렇게 코드가 뭔가 정상적(?)으로 보이기 시작합니다!!


그리고..

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax@5

  if ( argc != 2 || *argv[1] != 'p' || argv[1][2] != 'q' || argv[1][1] != 'd' )
  {
    printf(Son_I_am_disappoint);
    result = 0;
  }
  else
  {
    printf(Good_Job);
    result = 0;
  }
  return result;
}

argv[1] 이 pdq 이면 성공하는 간단한 문제(?)였습니다.




C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_15L>Lab15-01.exe pdq
Good Job!



질문

1. 이 바이너리에서 사용한 안티디스어셈블리 기법은 무엇인가?

xor eax, eax; jz +1; 을 이용한 안티디스어셈블리 기법이 사용되었습니다.

xor을 거치면 ZF가 1로 SET 되어 jz 는 더이상 조건분기가 아닌 무조건 분기가 되는 셈입니다.

그러나 디버거가 이를 해석할 때 jz 바로 다음에 나오는(+0) 코드를 opcode로 인식하고 이를 신뢰함으로써

코드가 깨져 보이는(뒤틀리는) 문제가 생기게 됩니다.




2. 디스어셈블리 과정에서 사용한 가짜 옵코드는 무엇인가?

.text:00401047                 xor     eax, eax
.text:00401049                 jz      short loc_40104C
.text:00401049 ; ---------------------------------------------------------------------------
.text:0040104B                 db 0E8h ; 
.text:0040104C ; ---------------------------------------------------------------------------
.text:0040104C
.text:0040104C loc_40104C:                             ; CODE XREF: _main+49j
.text:0040104C                 push    offset Good_Job ; "Good Job!"

가짜 opcode는 0xE8 로 call 입니다.




3. 이 기법이 몇 번이나 사용됐는가?

_main() 함수(0x401000)에서 5번 사용되었다.




4. 커맨드라인의 어떤 인자가 프로그램을 'Good Job!'이라고 출력되게 하는가?

두번째 인자(argv[1])가 pdq 일 때 'Good Job!'이 출력됩니다.

Comments