일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- ASM
- pwn
- format
- FSB
- 2018
- reversing
- rev
- Toddler's Bottle
- Bug
- shellcraft
- writeup
- string
- Bottle
- Reverse
- CTF
- shellcode
- CANARY
- practicalmalwareanalysis
- PMA
- Read
- BOF
- toddler
- pwnable.kr
- TUCTF
- anti
- Leak
- pico
- pwnable
- picoCTF
- Rookiss
- Today
- Total
제리의 블로그
PMA Lab15-01.exe 안티디스어셈블리 본문
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!'이 출력됩니다.