제리의 블로그

PMA Lab16-02.exe 안티디버깅 본문

카테고리 없음

PMA Lab16-02.exe 안티디버깅

j3rrry 2018. 8. 26. 16:30

Lab16-02.exe


질문

1. 커맨드라인에서 Lab16-02.exe를 실행할 때 어떤 일이 발생하는가?

C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_16L>Lab16-02.exe
usage: Lab16-02.exe <4 character password>




2. Lab16-02.exe를 실행할 때 어떤 일이 일어나는지 보고 커맨드라인의 파라미터를 추측해라.

C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_16L>Lab16-02.exe p@ss
Incorrect password, Try again.




3. 커맨드라인 패스워드는 무엇인가?

올바른 커맨드라인 패스워드는 bzrr이다.



4. Lab16-02.exe를 IDA Pro에 로드하자. main 함수에서 strncmp는 어디에서 발견했는가?

    CreateThread(0, 0, StartAddress, 0, 0, &ThreadId);
    Sleep(1000);
    v5 = strncmp(argv[1], &byte_408030, 4u);
    if ( v5 )
      sub_402148(aIncorrectPassw);
    else
      sub_402148(aYouEnteredTheC);

패스워드를 알아보기 위해서 정적디버깅을 해보았습니다.

.tls:0040123A 에서 strncmp가 사용되었고

byte_408030 의 문자열과 비교하는 것으로 밝혀졌는데요




5. 기본 설정으로 사용하는 OllyDbg에 이 악성코드를 로드하면 어떤 일이 발생하는가?

Terminated 됩니다. main(4011E0)에 BP 해봐도 똑같습니다.


6. Lab16-02.exe의 PE 구조에서 유일한 것은 무엇인가?

main 함수가 위치한 섹션을 보니 .text가 아니었습니다.

바로 .tls 였습니다.


7. 콜백 위치는 어디인가? (힌트: IDA Pro에서 Ctrl+E를 사용해보자)

Name           Address
TlsCallback_0  00401060
start          00402179 [main entry]

0x401060이 콜백 위치입니다.




8. 어떤 안티디버깅 기법을 이용해 디버거에서 즉시 종료하게 사용하는가? 어떻게 이 확인을 우회할 수 있는가?

FindWindowA 함수가 악성코드를 종료하는 데 사용됩니다.

.tls:00401060                 push    ebp
.tls:00401061                 mov     ebp, esp
.tls:00401063                 cmp     [ebp+arg_4], 1
.tls:00401067                 jnz     short loc_401081
.tls:00401069                 push    0               ; lpWindowName
.tls:0040106B                 push    offset ClassName ; "OLLYDBG"
.tls:00401070                 call    ds:FindWindowA
.tls:00401076                 test    eax, eax
.tls:00401078                 jz      short loc_401081
.tls:0040107A                 push    0               ; int
.tls:0040107C                 call    _exit

클래스 이름이 OLLYDBG인 윈도우를 찾으며, 발견하면 프로그램을 종료합니다.

PhantOm 같은 플러그인을 사용해 윈도우 클래스 이름을 변경하거나 0x40107C에 있는 exit 호출을 제거할 수 있습니다.



9. 안티디버깅 기법을 비활성화한 이후 디버거에서 봤던 커맨드라인 패스워드는 무엇인가?

FindWindowA 안티디버깅 기법을 굳이 비활성화지 않고 OllyDbg 대신 IDA로 해봤습니다.

.data:00408030 ; char byte_408030
.data:00408030 byte_408030     db 50h                  ; DATA XREF: StartAddress+22w
.data:00408030                                         ; StartAddress+60w ...

.data:00408030 에 하드 브포를 걸고 실행을 합니다.




argc가 1이면 "usage: Lab16-02.exe <4 character password>" 를 출력하고 종료되기 때문에

검증하는 부분을 넘어가기 위해서

파라미터도 아무거나 지정해줍니다.




---------------------------
Warning
---------------------------
Hardware breakpoint at 00408030 has been triggered
---------------------------
OK   
---------------------------

그러면 위와 같이 잡히게 됩니다.




.tls:004011D5 retn    4까지 실행시키면


password 는 '#zrr' 이라고 나옵니다.




10. 커맨드라인에서 동작할 때 디버거에서 패스워드를 발견했는가?

C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_16L>Lab16-02.exe #zrr
Incorrect password, Try again.

#zrr 을 넣어봤는데 올바른 패스워드가 아니었습니다.




11. 디버거와 커맨드라인에서 서로 다른 패스워드를 설명할 수 있는 기술은 무엇인가? 그리고 이런 기술을 어떻게 막을 수 있는가?

첫번째 기술: OutputDebugStringA

.tls:0040109B                 mov     bl, byte_40A968
...
.tls:00401111                 add     byte ptr password+1, bl

byte_40A968 이 패스워드 디코딩 알고리즘에 사용되는 것을 알 수 있는데

이 byte_40A968 은 OutputDebugStringA 함수의 결과에 따라 다른 값이 저장되도록 만들어 놓았습니다.

* OutputDebugStringA 는 디버거에게 문자열을 출력하는 것으로 성공/실패여부를 반환값으로 갖습니다.




.tls:00401035                 push    offset OutputString ; "b"
.tls:0040103A                 call    ds:OutputDebugStringA
.tls:00401040                 call    ds:GetLastError
.tls:00401046                 cmp     eax, [ebp+dwErrCode]
.tls:00401049                 jnz     short loc_40105A
.tls:0040104B                 mov     cl, byte_40A968
.tls:00401051                 add     cl, 1
.tls:00401054                 mov     byte_40A968, cl

.tls:0040103A 를 보면 OutputDebugStringA 가 사용되었습니다.




디버거에게 메시지가 전달된 모습을 확인할 수 있습니다.

OutputDebugString 부분은 0x401051의 add 연산을 못하도록 바이너리 패치하여 제거해줍니다.




두번째 기술: BeingDebugged 플래그

.tls:0040112B                 mov     ebx, large fs:30h
...
.tls:0040118B                 mov     bl, [ebx+2]
...
.tls:004011A2                 add     byte ptr password+2, bl

디버깅 중이면 BeingDebugged 플래그 1일텐데

그 1을 더하는 3줄짜리 어셈코드가 서로 떨어져있었다.

이런것도 난독화라면 난독화일 수 있겠죠 ㅎㅎ;;



번외


안티디버깅이 적용되어있으므로

정적디버깅만으로 프로그램을 간단히 분석하고

바이너리 패치로 키값을 뽑아내는 방법도 해보았습니다.

    v5 = strncmp(argv[1], &byte_408030, 4u);
    if ( v5 )
      sub_402148(&byte_408030);
    else
      sub_402148(aYouEnteredTheC);

main 함수에서

원래 "Incorrect password, Try again" 를 출력하는 부분을

byte_408030을 출력하도록 패치하면

대신 실패 문구 대신 패스워드를 출력할 것입니다.




C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_16L>Lab16-02.exe abcd
bzrrp@ss

그랬더니 "bzrr" 가 패스워드임을 알아냈습니다.

패스워드가 맞는지 다시한번 원본파일에 검증을 해봅니다.




C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_16L>Lab16-02.exe bzrr
You entered the correct password!

성공입니다.




책에는 byrr 이 패스워드라고 적혀있었는데

C:\ProgramData\chocolatey\lib\pmalabs\tools\Practical Malware Analysis Labs\Bina
ryCollection\Chapter_16L>Lab16-02.exe byrr
Incorrect password, Try again.

저는 뭐가 잘못된거일까요..


Comments