Be myself :: 'Reversing' 카테고리의 글 목록

달력

32024  이전 다음

  • 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
  • 29
  • 30
  • 31

'Reversing'에 해당되는 글 16건

  1. 2015.05.08 elf DWARF관련..
  2. 2015.01.28 vmware 디버깅
  3. 2014.10.17 peda 설치법
  4. 2014.07.29 지뢰 찾기 핵 1
  5. 2014.07.28 치트엔진을 활용한 환세취호전 핵 2
  6. 2014.05.17 DLL Injection 1
  7. 2014.05.16 PEB를 활용한 안티디버깅
  8. 2014.05.16 WinDbg, xp 연동
  9. 2014.05.15 SEH를 이용한 안티디버깅 1
  10. 2014.05.15 TLS 콜백 안티디버깅

elf DWARF관련..

Reversing 2015. 5. 8. 11:48

c++에서 익셉션이 발생했을 때 (try~catch 구문에서) stack unwinding 과정을 거쳐 catch문으로 eip가 이동해 핸들러가 실행되게 되는데, 익셉션이 발생한 시점에서 바로 예외 핸들러가 실행되게 되면, 스택이나 레지스터가 제대로 세팅된 상태가 아니기 때문에 에러가 난다. 이를 방지하기 위해 DWARF(elf 디버깅 정보 저장)에 byte code로 eh_frame섹션에 저장되어 있다. 이 byte code들은 libc의 DWARF 인터프리터에 의해 실행된다. 

DWARF 정보를 알기 위해 readelf -w [elf file name]과 같이 입력하면 된다.

flack3r@ubuntu:~/prob$ readelf -w echo

Contents of the .eh_frame section:


00000000 0000000000000014 00000000 CIE

  Version:               1

  Augmentation:          "zR"

  Code alignment factor: 1

  Data alignment factor: -8

  Return address column: 16

  Augmentation data:     1b


  DW_CFA_def_cfa: r7 (rsp) ofs 8

  DW_CFA_offset: r16 (rip) at cfa-8

  DW_CFA_nop

  DW_CFA_nop


00000018 0000000000000024 0000001c FDE cie=00000000 pc=0000000000400610..00000000004006b0

  DW_CFA_def_cfa_offset: 16

  DW_CFA_advance_loc: 6 to 0000000000400616

  DW_CFA_def_cfa_offset: 24

  DW_CFA_advance_loc: 10 to 0000000000400620

  DW_CFA_def_cfa_expression (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus)

  DW_CFA_nop

  DW_CFA_nop

  DW_CFA_nop

  DW_CFA_nop


00000040 000000000000001c 00000044 FDE cie=00000000 pc=0000000000400794..00000000004007c0

  DW_CFA_advance_loc: 1 to 0000000000400795

  DW_CFA_def_cfa_offset: 16

  DW_CFA_offset: r6 (rbp) at cfa-16

  DW_CFA_advance_loc: 3 to 0000000000400798

  DW_CFA_def_cfa_register: r6 (rbp)

  DW_CFA_advance_loc: 39 to 00000000004007bf

  DW_CFA_def_cfa: r7 (rsp) ofs 8

  DW_CFA_nop

  DW_CFA_nop

  DW_CFA_nop


여기서 CIE는 익셉션이 발생했을 때 공통적으로 실행되는 부분이고 FDE는 특정 예외 처리 부분이라고 한다.

DW_CFA_val_expression 에 대한 설명은 http://www.dwarfstd.org/doc/040408.1.html 에 있다.


'Reversing' 카테고리의 다른 글

vmware 디버깅  (0) 2015.01.28
peda 설치법  (0) 2014.10.17
지뢰 찾기 핵  (1) 2014.07.29
치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
DLL Injection  (1) 2014.05.17
Posted by flack3r
|

vmware 디버깅

Reversing 2015. 1. 28. 11:56

.vmx파일에 다음과 같이 추가한다.

debugStub.listen.guest32 = "TRUE"
debugStub.hideBreakpoints = "TRUE"
monitor.debugOnStartGuest32 = "TRUE"

그 후 vmware를 실행시키고 IDA로 remote gdb debugger선택 후 localhost, 8832 port로 접근한다. 그 후 원하는 주소에 브레이크걸고 리버싱 ㄱㄱ

'Reversing' 카테고리의 다른 글

elf DWARF관련..  (0) 2015.05.08
peda 설치법  (0) 2014.10.17
지뢰 찾기 핵  (1) 2014.07.29
치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
DLL Injection  (1) 2014.05.17
Posted by flack3r
|

peda 설치법

Reversing 2014. 10. 17. 17:34

gdb와 연계되는 peda 프레임워크 설치법이다.

gdb가 python 3.0이상버전과 연계되어 있으면 오류가 뜬다. 그래서 2점대 버전으로 gdb degrade 해야 하는데 이 때 방법은 다음과 같다.

1. synaptic packge manager 설치

2. 저장소에 다음 추가  deb http://kr.archive.ubuntu.com/ubuntu/ precise main (12.04의 저장소이다.)

3. 시냅틱 새로고침 후 gdb 검색하고 force version 메뉴 선택후 설치

4. echo "source ~/peda/peda.py" >> ~/.gdbinit

끝.

peda 설치는 다음에서 할 수 있다.

https://github.com/longld/peda

'Reversing' 카테고리의 다른 글

elf DWARF관련..  (0) 2015.05.08
vmware 디버깅  (0) 2015.01.28
지뢰 찾기 핵  (1) 2014.07.29
치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
DLL Injection  (1) 2014.05.17
Posted by flack3r
|

지뢰 찾기 핵

Reversing 2014. 7. 29. 10:38

<지뢰 찾기 패치>

윈도우 xp 시리즈 지뢰 찾기를 시작할 때 지뢰가 보이도록 패치 해 보겠다.

사용한 툴은 오직 OllyDbg뿐이다.

자, 일단 올리디버거로 실행시키고 F8로 쭉~ 따라 가다 보면 다음과 같은 루틴을 만난다.


1005330이 0이 될 때까지 반복하는 구간인데, 초급 난이도에서 지뢰가 10개임을 생각하면 10개만큼의 지뢰를 배치하는 것 같다. 사실, 이 루틴을 찾는 방법은 그냥 무작정 F8로써 분석해 가면서 찾아도 되는데, 나 같은 경우는 srand()함수 부분을 먼저 찾았다. (지뢰가 무작위로 배치될 것이기 때문에 이 부분위주로 찾으면 지뢰가 배치되는 부분을 찾을 수 있다.) 그 후 이 부분 위주로 분석하고 지뢰를 밟았을 때, 지뢰를 보여주는 함수를 찾았고, 이 부분으로 Jmp하게 해서(인라인 패치를 통해) 지뢰가 시작할 때 보여지도록 했다.

아무튼, 위 그림 부분을 하나하나 분석하다 보면 메모리에 다음과 같은 값들이 써진다.

지뢰의 개수를 나타내는 곳은 0x1005334부분이고 이 메모리 근처에 지뢰를 배치하는 판(?)을 그리는 것 같다. 지뢰가 위치하는 곳은 0x8F로 표시하는 듯 하다. 따라서 게임이 끝났을 때, 지뢰가 있는 부분을 표시하기 위하여 0x8F부분에 반드시 접근할 것이므로 저 부분에 하드웨어 브레이크 포인트를 걸어 실행 후 지뢰를 밟으면 지뢰를 보여주는 함수가 나온다.!!


0x1002F80 으로 시작되는 함수이다. 자 그럼, 우린 지뢰를 배치하고, 화면에 뿌리고 그 이후에 사용자의 입력 값을(클릭하는 것) 받는 루틴에서 잠깐 프로그램의 실행을 0x1002F80으로 돌리고 다시 원래의 실행을 하면 지뢰를 보는 상태로 게임을 할 수 있다. 그래서 다음과 같이 패치하자.

(사용자의 입력 값을 받는 루틴이다.)

여기서 우린 0x1002380부분에서 패치를 할 것이다. (이 부분에 패치를 하는 이유는 JMP명령어가 5바이트를 차지하므로 적당한 부분을 고른 것일 뿐이다.) 다음과 같이 바꾸자

이제 오른쪽 클릭-> Copy to executable -> All modifications 을 누른 후 오른쪽 클릭 -> save file을 눌러 패치 파일을 저장하면 모든 패치가 끝나게 된다.

'Reversing' 카테고리의 다른 글

vmware 디버깅  (0) 2015.01.28
peda 설치법  (0) 2014.10.17
치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
DLL Injection  (1) 2014.05.17
PEB를 활용한 안티디버깅  (0) 2014.05.16
Posted by flack3r
|

환세취호전 핵 만들기

오랜만에 고전게임이 생각나서 환세취호전을 했는데 너무 재미있었다. 그래서 핵까지 만들게 되었다. ㅋㅋㅋ

사용한 툴은 OllyDbg와 치트엔진 그리고 환세취호전을 창모드로 만들어 주는 인터넷에서 돌아다니는 툴을 사용했다. 핵이 적용된 save파일은 밑에서 다운받자.


savedat2.dat

환세취호전.zip


자 일단, 핵을 만들기 전에 한번 게임 해봐야 할 것 같아 한번 켰더니 '켠킴에 왕까지' 프로그램 빙의되서 엔딩까지 보고 말았다. ㅋㅋㅋ

음. 암튼 치트 엔진을 키고! 일단 돈부터 조작해보자.

돈에 해당하는 값을 입력하고 First Scan을 누르고 224의 값을 가진 주소값(변수)들을 전부 출력한다.

그 후 몬스터 한 마리 잡고 돈이 올라갔을 때, Scan Type에 Changed value를 선택하고 First Scan옆에 있는 Next Scan을 누른 후 값이 변한 변수들을 확인해서 현재 돈과 같은 값을 가지는 변수를 찾는다. 그것이 바로 돈의 변수 주소 값이다.


(첫 번째 스캔 눌렀을 때)


(두 번째 scan)

이러한 원리로 체력, 기력, 공격력, 방어력 등의 변수의 주소 값을 구할 수 있다. (레벨업을 하면 이 값이 변동되므로 변한 값 위주로 scan해서 파악함.) 주의할 점은 캐릭터들의 능력 치는 구조체 형식으로 저장이 되어 있을 것임을 예측 할 수 있다. 따라서 캐릭터 별로 능력치의 값들은 서로 가까운 주소 값에 몰려 있을 거라 생각할 수 있다. 돈을 가진 변수 또한 마찬가지 이므로 값을 찾을 때 0x400000 부분의 주소 위주로 찾으면 쉽게 다 찾을 수 있다.

다음은 캐릭터 별 체력, 기력, 공격력, 방어력을 찾은 화면이다.

자 이제 캐릭터 별 레벨, 체력, 기력, 공격력, 방어력 을 완전히 통제할 수 있고, 사실 혼자 핵을 쓸려면 이대로 플레이 하면 된다. 하지만, 우린 다른 사람도 우리의 핵 패치를 이용하고 싶을 것이므로(그래야 할 텐데..) 범용성을 위해 어떤 프로그램이나 파일을 만들어야 한다.

생각을 해봤는데, DLL인젝션을 통해서 캐릭터 특성 값을 하나하나 변경할 수 있지만 너무 큰 프로젝트가 될 것 같고 간단하게 특성 값들이 조작된 Save파일을 만든다면, 다른 사람들도 Save파일을 불러오기만 하면 거의 무적이 된 게임 캐릭터들을 만나볼 수 있을 것이다. ㅎㅎ

그럼 Save파일을 불러와 그 구조를 확인하자.

흠.. 그냥 이렇게 봐선 뭐가 뭔지 모른다. 그렇지만, 어떤 덩어리(패턴)등이 3번 반복되는 것을 볼 수 있는데(화면엔 2덩어리 밖에 안 잡혔다.) 게임에서 우리가 플레이 하는 캐릭터가 3명임을 감안 할 때, 이 덩어리들은 각 캐릭터들의 특성을 저장한 구조체임을 추측 할 수 있다.

이를 더 확실히 하기 위해 OllyDbg를 열고 치트엔진으로 확인한 변수들의 주소 값을 확인해 어떠한 형태로 캐릭터 특성 값들이 저장되는지 확인 해 봐서 Save파일과 비교한 후 Save파일의 어떤 부분의 값이 무엇을 뜻하는지 확인하는 과정을 거치고 알아 낸 후 조작하고 파일을 저장하면 끝이다. ㅋㅋㅋ 무슨 말인지 몰라도 상관없다. 다음의 그림들을 보면 확실히 알 것이다.

아타호의 level은 0x457756주소에 2Byte형태로 저장되어 있다. 이를 올리디버거로 확인 해 보면 다음과 같다.

0x457756 부분을 확인 해 보면 저런 식으로 값이 들어가 있다. [01 00]->아타호 레벨 부분이고 다음 [1E 00 1E 00 1E 00] 부분은 아타호의 체력과 관계된 부분이다. 근데 위에 빨간색으로 표시된 부분은 어디서 많이 본 것 같지 않나? 그렇다. 아까 save파일에 덩어리 부분의 일부이다.

위의 offset값 0x11A 부분부터 올리디버거로 확인한 저 빨간색 블록과 비교해 보자.

거의 똑같지 않나? 그렇다. 올리디버거에서 확인한 구조체 부분과 save파일의 구조체부분이 다르지 않다는 것이다. 그렇다는 것은 치트엔진과 Ollydbg를 이용해 save파일에서 캐릭터들의 특성 값이 어디에 위치하는지 알아 낼 수 있다는 것을 의미한다.

그래서 하나하나 알아보면 다음과 같다.

여기서 공격력-update와 방어력-update부분은 레벨업 시 레벨업을 처리하는 함수가 참조하는 부분인데, 이 부분을 조작하지 않으면 캐릭터가 레벨 업을 할 때 애써 조작한 공격력이나 방어력이 원래대로 돌아가 버린다. 암튼 위에 부분의 구조는 아타호의 값들인데 다른 캐릭터들의 특성값들도 동일한 구조로 저장되어 있으므로 여기까지 이해 했다면 나머지 린샹이나 스마슈의 특성값들은 쉽게 찾을 수 있을 것이다.

다음은 내가 파악한 값들이다.

<raw 0x8>

4바이트 -> 돈

--------------------아타호------------------

<0x457756>

<raw 11a>

첫째 2바이트 -> 레벨

둘째 2바이트*3 ->체력

셋째 2바이트*3 ->마나

 

<raw 142>

2바이트 -> 공격력

 

<raw 146>

첫째 2바이트 -> 방어력

 

<0x45780E>

<raw 304>

첫째 2바이트->공격력 업데이트

<raw 308>

첫째 바이트 ->방어력 업데이트

--------------------------------------------

 

-------------------린샹---------------------

<0x45782E>

<raw 0x320>

첫째 2바이트 -> 레벨

둘째 2바이트*3 -> hp

셋째 2바이트*3 -> mp

 

<0x457844>

<raw 0x358>

첫째 2바이트 -> 공격력

+2바이트

둘째 2바이트 -> 방어력

 

<raw 0x51a>

첫째 2바이트 -> 공격력 업데이트

+2바이트

둘째 2바이트 -> 방어력 업데이트

-----------------------------------------

 

------------------스마슈--------------------

<0x457906>

<raw 54c>

첫쨰 2바이트 ->레벨

둘째 2바이트*3 ->hp

둘째 2바이트*3 ->mp

 

<raw 574>

첫째 2바이트 ->공격력

+2바이트

둘째 2바이트 ->방어력

 

<raw 736>

첫째 2바이트 -> 공격력 업데이트

둘째 2바이트 -> 방어력 업데이트

자, 이렇게 해서 레벨, 체력, 공격력 등을 조작해서 자기가 원하는 값으로 세팅한 후 저장하면 트레이너 save파일이 만들어 진다. ㅎㅎ

완성된 save 파일을 로드 했을 때의 사진이다.

'Reversing' 카테고리의 다른 글

peda 설치법  (0) 2014.10.17
지뢰 찾기 핵  (1) 2014.07.29
DLL Injection  (1) 2014.05.17
PEB를 활용한 안티디버깅  (0) 2014.05.16
WinDbg, xp 연동  (0) 2014.05.16
Posted by flack3r
|

DLL Injection

Reversing 2014. 5. 17. 14:13

1 개요

DLL인젝션하는 방법들을 간단히 개념적으로만 알아볼 예정이다. 다음에 많은 사람들이 인젝션 연습으로 많이 하는 '지뢰 찾기' 패치 등을 하면서 실습을 할 예정이다.

 

2 dll 인젝션

일단, DLL인젝션을 하는 방법들을 알아보자.

1. SetWindowsHookEx() 를 이용한 윈도우 메시지 후킹.

이 방식은 API후킹과 함께 대표적인 후킹방법 이기도 하다.
윈도우는 GUI방식을 제공하고, GUI방식으로 동작할 때, 키보드의 입력이나 마우스의 입력 등은 메시지방식(Event Driven)으로 처리된다. 이 때, 메시지를 잠시 보관하는 버퍼가 OS에도 존재하고, 어플리케이션 계층영역에서도 존재하게 되는데, SetWindowsHookEx()를 하면, 이 사이에서 메시지를 가로챌수 있다. 또 한 이 함수는 한번 적용해 훅을 설치하면 어떤 프로세스에서 해당 메시지가 발생했을 때 운영체제가 DLL을 강제로 인젝션 하고 hook procedure를 호출한다. 제일 편하고, 간단하긴 한데 아예 메시지 호출이 안되도록 하진 못해서 한계가 있다.

2. CreateRemoteThread() 함수를 통한 DLL Injection

이 방법도 DLL Injection을 한번이라도 공부 해 보았다면 알고 있을법한 API이다. 이 방법의 핵심은 상대 프로세스로 하여금, LoadLibrary()를 호출하게 만들어 DLL을 로딩시키는 것이다.

보통 OpenProcess로 DLL Injection을 수행할 프로세스의 핸들을 얻고, VirtualAllocEX함수와 WriteProcessMemory함수로 LoadLibrary의 인자에 해당하는 DLL의 경로를 쓴다. 그 다음 GetModuleHandle과 GetProcAddress로 LoadLibrary()의 주소 값을 얻은 다음 CreateRemoteThread()함수를 통해 목표 프로세스가 LoadLibrary함수를 호출하도록 한다.

3. Applnit_DLLs

레지스트리를 이용하는 방법이다. \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows 에서 Applint_DLLs의 값을 인젝션을 원하는 DLL경로 문자열을 쓰고 LoadApplint_DLLs 값을 1로 변경한 후 재부팅하면 실행되는 모든 프로세스에 해당 DLL이 인젝션 된다.

4. PE패치를 통한 인젝션

이 방법은 PE에서 IDT에 인젝션 하고자 하는 DLL을 추가시킴으로써 인젝션 하는 방법이다.

'Reversing' 카테고리의 다른 글

지뢰 찾기 핵  (1) 2014.07.29
치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
PEB를 활용한 안티디버깅  (0) 2014.05.16
WinDbg, xp 연동  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
Posted by flack3r
|

1 개요

PEB를 이용한 안티디버깅 기법을 알아보고 우회법을 파악한다.

2 PEB

PEB(Process Environment Block)은 프로세스에 관한 정보를 담고 있는 구조체이다. 이를 WinDbg상에서 확인해 보자.(window xp sp3환경에서 테스트 했다)

여기서 안티 디버깅에 사용되는 멤버는 BeingDebugged, Ldr, ProcessHeap, NtGlobalFlag 가 있다. 이 각각의 것들을 '리버스코어'에서의 StaAD_PEB.exe예제에서 알아보고 우회방법 까지 다루겠다.

2-1 BeingDebugged

BeingDebugged 멤버를 어떻게 사용하는지 예를 보자.

FS:[18]은 TEB의 주소값이다. TEB:[30]은 PEB의 주소 값이다. PEB[2]가 바로 BeingDebugged멤버인데 이 값은 디버그 중일 때 1이된다. 그렇다면 회피방법 또한 간단하다. PEB[2]의 값을 0으로 만들어 주면 된다.

TEB가 무엇인지 설명을 빠뜨렸는데, 다음과 같은 멤버들을 가진다. 멤버들을 보면 프로그램 시작주소나 PEB(프로세스 정보) 등을 가지는데 TEB는 각 쓰레드 마다 가지는 구조체이다.

 

2-2 PEB.Ldr

이번엔 PEB.Ldr멤버가 어떻게 사용되는지 알아보자. Ldr은 프로세스에 로딩된 Dll의 로딩베이스 주소를 알아낼 때 많이 쓰이는데, 힙 영역에 존재하는 특징을 이용한 것이다. 디버깅시 사용되지 않는 힙영역의 값이 EEFEEEFE로 초기화 되는데 이 특징을 이용한 것이다.

*주의할점)
윈도우 xp이하 적용되는 내용이다. Win 7, 8 등은 안 된다.

위의 그림을 보면, NtCurrentTeb 함수를 CALL EAX로 호출하는데 이 함수는 TEB의 주소값을 리턴한다. 즉, EAX엔 TEB주소값이 들어가게 된다.

자, 위의 루틴을 보면, PEB.Ldr 값에서부터 1씩 증가해 가며 EEFEEEFE값을 가지나 확인하는 루틴이다. 그럼 우회법은 Ldr의 주소값을 참조하여 메모리값을 본 다음 EEFEEEFE라고 쓰여진 부분을 0으로 초기화 시키면 끝이다. 다음과 같이.

 

2-3 Process Heap

이번엔 Process Heap의 flag를 이용해 안티 디버깅을 수행하고 있다. 아까 EBX에 PEB의 주소값이 있었으므로, 401112주소에서 [EBX+18]은 PEB.ProcessHeap을 가리키고, ProcessHeap구조체에서 12(0xC)만큼 떨어진 곳에 flag값이 존재한다. 이 flag값은 디버그 중이 아니면 2의 값을 가지므로 이 값을 2로 하면 우회까지 완성된다.

ProcessHeap구조체는 다음과 같은 멤버들을 가진다. 환경이 xp가 아니라서 멤버들의 위치가 xp에서의 HEAP과 다르다. XP에선 Flags가 0xc에 위치하고 ForceFlags가 0x10에 위치한다.

<출처: http://gogil.kr/24>

다음 ProcessHeap의 ForceFlags값을 이용하는 방법이다. 이 값은 정상 실행중일 때, 0이 된다. 따라서 이 값을 0으로 하면 우회까지 완벽하다.

아까 EDI에 PEB.ProcessHeap값이 있었으므로 [EDI+10]은 ForceFlags의 값이 된다. 401152주소를 보면 ESI이 0인지 아닌지 확인하는 루틴이 있고, 0이면 Not debugging이 뜨도록 되어있다. 우리는 [EDI+10]의 값을 0으로 바꾸면 된다.

2-4 NtGlobalFlags

TEB.NtGlobalFlag 값은 디버깅 중일 때 0x70의 값을 가진다. 따라서 이 값을 0으로 만들어 줘버리면 우회가 가능하다.

아까 EBX에 TEB의 주소 값이 있었으므로 0x68만큼 떨어진 위치에 NtGlobalFlag가 위치하게 된다. 이 값이 0x70인지 확인하는 루틴이 40117E에 있다. 우린 이 값을 0으로 만들면 된다.

'Reversing' 카테고리의 다른 글

치트엔진을 활용한 환세취호전 핵  (2) 2014.07.28
DLL Injection  (1) 2014.05.17
WinDbg, xp 연동  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
TLS 콜백 안티디버깅  (0) 2014.05.15
Posted by flack3r
|

WinDbg, xp 연동

Reversing 2014. 5. 16. 16:13

1 개요

Windbg와 Vmware에서 XP를 연동하는 법을 알아본다.

2 vmware 세팅

1. Edit virtual machine settings를 누른다.

2 Serial Port 를 추가하고 use named pipe 의 마지막에 com_1라 적힌걸 기억하라 WinDbg에서 연결할 때 필요하다.

3 xp세팅

1. 내 컴퓨터-> 속성-> 고급-> [시작 및 복구] 설정 을 누른다

2. 편집을 눌러준다.

3. 위와 같이 제일 마지막 줄에 아래와 같이 추가해준다.
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="XP kernel debug" /fastdetect /debugport=com1 /baudrate=115200

4 windbg 세팅

1. 윈디버그 속성창에서 '대상'에
"C:\Program Files\Windows Kits\8.0\Debuggers\x86\windbg.exe" -k com:port=\\.\pipe\com_1,baud=115200,pipe,reconnect

이런 식으로 입력한다. 프로그램 위치와 버전이 다를 수 있으니 확인하고 적용한다. 핵심은 경로 + 뒤에 옵션을 주는 것이다. 여기서 주의할 점은 \\.\pipe\com_1이 부분에 com_1이라고 아까 vmware설정에서 적었던 이름 그대로 넣어주어야 한다.

2. 이제 Windbg를 실행시킨 후 xp를 실행시키면 된다. 그 후 Ctrl+Break를 누르면 디버깅 상태가 되고 F5나 g를 누르면 running상태가 된다.

'Reversing' 카테고리의 다른 글

DLL Injection  (1) 2014.05.17
PEB를 활용한 안티디버깅  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
TLS 콜백 안티디버깅  (0) 2014.05.15
인라인 패치  (0) 2014.05.11
Posted by flack3r
|

1 개요

SEH(Structured Exception Handler)는 윈도우에서 제공하는 예외처리 매커니즘이다. 이 SEH는 안티 디버깅 기법으로도 사용되는데 SEH가 무엇인지, 어떻게 안티 디버깅으로 사용되는지, 우회법은 무엇인지 등을 알아보자.

2 SEH(프로그래밍으로)

예외 처리의 과정을 알아보자. 우선 프로그램에서 예외가 발생할 경우, OS는 프로세스에게 예외처리를 맡긴다. 하지만, 프로그램이 적절한 예외처리를 하지 못할 경우 OS에서 오류처리를 한답시고 프로그램을 종료시켜 버린다. 이것이 일반적인 예외처리 메커니즘인데 디버깅을 하는 경우, 예외처리 루틴을 디버기(디버그를 수행하는 프로그램)에 맡겨버린다. 이러한 상황을 한번 보자.

다음과 같이 예외처리를 하는 프로그램을 작성하였다.

#include<Windows.h>
#include<stdio.h>
int main(void)
{
	int seh_flag = 0;
	int a = 1;
	int b = 0;
	int result = 0;
	__try{
		result = a / b;
	}

	__except(EXCEPTION_EXECUTE_HANDLER){
		seh_flag = 1;
		printf("normal processing \n");
	}

	if (seh_flag == 0)
	{
		printf("debuge detected \n");
		getchar();
	}
	getchar();
	return 0;
}

0으로 나누는 것은 EXCEPTION_INT_DIVIDE_BY_ZERO예외를 발생 시킨다. 이 것을 그냥 실행했을 때와 올리디버그상에서 실행했을 때를 보자.

<일반 실행> <디버그로 실행>

왜 이렇게 될까? 그것은 앞에서 설명 했듯이 예외 발생 시 디버기에서 예외처리를 담당하기 때문에 프로그램에서의 예외처리는 무시된다. 이는 올리디버거 상에서 확인할 수 있다.

IDIV 즉, 나누는 과정에서 break되고 과정을 살펴 보면, normal processing이라 뜨는 루틴이 생략되는 것을 알 수 있다.

그렇다면 이를 우회하는 방법은 이제 답이 나온 셈이다. 아예 예외가 발생하는 명령어 부분을 고쳐서 디버깅을 다시 하던지, 아님 올리디버거에 예외처리를 디버기(디버깅을 당하는 프로그램)에게 맡기는 옵션을 주면 정상 실행된다.

위 그림과 같이 설정하면 된다.

 

3 SEH(어셈블리로)

아깐, 디버기에서의 예외처리를 이용하여 안티디버깅을 했지만 이번엔, SEH chain에 직접 예외 핸들러를 등록해서 예외처리 루틴에서 안티디버깅을 수행한다.

먼저 SEH를 등록하는 과정을 보자.

처음 PUSH한 것이 예외를 처리하는 핸들러의 주소 값이다 FS:[0]는 TEB의 주소 값인데, NtTib.ExceptionList구조체 멤버의 주소값이기도 하다. TEB에 관한 내용은 다음에 설명하도록 하겠다. 즉 위에서 명령어가 수행되면, 전 FS:[0] (SE핸들러 멤버를 가진 구조체의 주소값 더 자세히는 EXCEPTION_REGISTRATION_RECORD 구조체의 첫 번째 멤버인데 자세한 내용은 구글을 통해 알아 보시길) 를 스택에 넣고 SEH를 등록하는 과정이다.

이후 프로그램 과정에서 다음과 같이 일부로 예외를 발생시킨다.

EAX의 주소값이 0인데 이 부분에 1이라는 값을 넣고 있다. 이제 예외가 발생했으므로 우리가 아까 등록한 예외 핸들러가 실행될 것이다.

어디서 많이 본 명령어 이지 않은가? 0x40105E~ 0x401064명령어를 보면 TEB의 30번째 멤버(PEB)에 접근해 PEB의 BeingDebugged멤버에 접근해 이 값이 1인지 아닌지 판별하는 IsDebuggerPresent() 함수의 내용과 같은 명령어를 수행한다.

여기서 ESI엔 예외가 발생하기 전 pContext값이 들어가게 된다. 예외처리 핸들러의 3번째 매개변수이다. Context엔 예외가 발생하기 전 레지스터나 세그먼트 들의 값이 저장되어 있다. Context는 각 스레드마다 내부적으로 가지고 있다. Context가 존재하는 이유는, 전에 OS kernel관련 포스팅에 게시되어 있는데 멀티스레딩 환경에서 필수적이기 때문이다.

아무튼, Context에서 B8만큼 떨어진 값에는 Eip의 값이 들어 있으므로, 이 값을 변경하면 예외 핸들러루틴이 마무리되면, 설정된 주소값으로 JMP하게 된다. 따라서, 디버깅 중이라면, 40106A로 점프하게 되는게 이 명령어를 보면 Eip를 401023으로 설정하고 있다. 이 값에 해당하는 영역으로 가보자.

예상 했듯이, 디버거가 발견되었다는 메시지박스가 출력된다.

우회방법은 위의 __try, __except방법과 같고 그 후 위의 IsDebuggerPresent() 함수의 우회법을 적용하면 된다.

'Reversing' 카테고리의 다른 글

PEB를 활용한 안티디버깅  (0) 2014.05.16
WinDbg, xp 연동  (0) 2014.05.16
TLS 콜백 안티디버깅  (0) 2014.05.15
인라인 패치  (0) 2014.05.11
Upack 분석중 정리  (0) 2014.05.10
Posted by flack3r
|

1 개요

TLS콜백 함수가 어떻게 안티 디버깅으로 사용되는지 어떻게 우회가 가능한지 살펴 볼 것이다.

 

2 TLS

TLS(Thread Local Storage)는 쓰레드 별로 독립된 메모리 공간이다. 프로세스에서 전역변수나 static변수를 마치 쓰레드의 지역변수처럼 사용하고 싶을 때 사용된다. 하지만 TLS 콜백 함수가 EP코드가 실행되기 전에 동작하는 특징을 이용해 안티디버깅 기법으로도 사용 된다.

일단 TLS콜백함수를 사용하는 소스코드를 살펴 보자.

#include<Windows.h> #pragma comment(linker, "/INCLUDE:__tls_used") //링커설정. tls사용함으로 void NTAPI Tls_Callback(PVOID THandle, DWORD Reason, PVOID Reserved) { if (IsDebuggerPresent()) //IsDebuggerPresent()함수를 이용해 디버깅 중인지 확인 {         MessageBoxA(NULL, "Not allowed Debuging..", "TLSCallback",MB_OK);         ExitProcess(1); } } #pragma data_seg(".CRT$XLX") //TLS콜백 사용시 꼭 필요한 섹션 PIMAGE_TLS_CALLBACK TLS_CALLBACk[] = { Tls_Callback, 0 }; // TLS callback 함수 등록 #pragma data_seg() int main(void) { MessageBoxA(NULL, "Hi There! this is Inj3cti0n ! ", "mainbox", MB_OK); return 0; }

주석처리를 해놓아서 딱히 어려운점은 없을 것 같다. IsDebuggerPresent 함수가 처음 소개되었는데, 이는 PEB에서 3번째 멤버(PEB.BeingDebugged)를 이용해 디버깅중인지 아닌지 확인하는 함수이다. 자세한 내용은 다음에 설명하도록 하겠다.

자 그럼 이렇게 컴파일 된 파일을 실행시켜 보겠다.

잘 된다. 그럼 올리디버거로 열어 보겠다.

열리지 않는다. 자 일단 누군가가 어떠한 파일을 올리디버거로 열었을 때 디버깅이 되지 않는다면 무척 당황스러울 것이다. 그렇다면 필자는 원인이 뭔지 확인하기 위해 제일 먼저 PEview로 확인을 해 볼 것이다. 그래서 확인을 해 봤더니 TLS Table이 있는 것이 아닌가.

그렇다면 이 파일은 TLS Callback을 이용하여 안티 디버깅을 했을 가능성이 많다. 테이블 내용을 살펴 보면 다음과 같다.

여기서 제일 중요한 맴버는 Address of Callbacks이다. 여기서 주의할 점은 Callbacks 복수로 나타나 있다. 그래서 이 값은 배열의 주소 값을 나타내며 여러 개의 TLS Callback 함수를 등록할 수 있다는 것을 암시한다. 이 값은 VA값으로 나타나 있다.

3 TLS callback 디버깅

자 그럼 어떻게 디버깅은 어떻게 할까. EP가 실행되기 전에 디버깅을 해야 하므로 일단, 올리디버거 옵션부터 변경해 준다.

그리고, PEview를 이용하여 TLS 테이블에서 TLS콜백의 시작주소 값을 알아 낸 후 올리디버거에서 브레이크걸고 IsDebuggerPresent함수를 우회하면 된다.

디렉토리에서 TLS함수 배열 주소를 찾은 뒤

Hex에디터에서 함수 시작 값을 찾고

올리디버거에서 BP를 걸고 디버깅해서 우회하면 성공!

 

4 수작업으로 tls추가

지금까지 살펴 보았듯이 PE구조에 TLS table만 추가해 주면 코드를 수정하지 않고 패치가 가능하다. 직접 해보자.

직접 패치 시킬 때, 빈 공간을 잡아야 하기에 빈 섹션을 이용하거나, 마지막 섹션의 크기를 늘리거나, 마지막 섹션을 추가하거나 하는 방법이 있다. 여기서 우린 마지막 섹션의 크기를 200바이트 늘려서 해보도록 하자.


<Image_section_header .rsrc>

Size of Raw Data값을 Hex에디터를 이용해 400으로 수정하고 마지막 부분에 200바이트를 추가 시킨다. 그 다음 Optional_header의 TLS Table값을 설정해 준다.

다음엔, .rsrc섹션에 Characteristics값을 IMAGE_SCN_CNT_CODE, IMAGE_SCN_CNT_MEM_EXECUTE, IMAGE_SCN_CNT_WRITE의 값으로 설정한다

 

마지막으로 IMAGE_TLS_DIRECTORY의 멤버를 참고하여 구성한다.

여기서 RETN 0C를 하는 이유는. TLS callback 함수의 인자의 개수가 3개이기 때문에 보정해 주는 역할을 하는 것이다.

이제 마지막으로 할 일은 FileOffset 9230부분에 명령어를 입력하는 것인데, 이 땐, 올리디버거를 이용해 어셈프로그래밍을 하는 것이 쉽다.

다음과 같이 입력하자.

그런 다음 Copy to executable –selection –Save file 을 선택해 저장한 후 실행 시키면 메시지 박스가 뜬 다음 실행되는 걸 볼 수 있다.

<실행 후 첫 번째 메시지> <두 번째 메시지>

'Reversing' 카테고리의 다른 글

WinDbg, xp 연동  (0) 2014.05.16
SEH를 이용한 안티디버깅  (1) 2014.05.15
인라인 패치  (0) 2014.05.11
Upack 분석중 정리  (0) 2014.05.10
UPX압축 디버깅  (0) 2014.05.09
Posted by flack3r
|