네트워크 보안 | 침투 테스트 입문 학습, 제로 기본 입문부터 숙련도까지 - 동적 분석 기술 OllyDbg 사례 상세

목차

1. 준비

 2. 디버깅 대상 파일 로드

 3. 단일 단계 추적

4. 중단점 설정

5. 디버깅 분석


 

1. 준비


Windows 프로그램 분석은 Windows에서 API 기능을 사용하는 한 단서를 찾는 사람들에게 일부 정보를 숨기기가 더 어렵기 때문에 DOS 프로그램 분석보다 훨씬 쉽습니다. 따라서 프로그램을 분석할 때 어떤 API 함수를 진입점으로 삼느냐가 더 중요하다. 프로그래밍 경험이 있다면 이와 관련하여 더 편리할 것입니다.

이해의 편의를 위해 그림 25와 같이 TraceMe의 일련 번호 확인 프로세스를 간략하게 살펴보겠습니다. 텍스트 상자에 사용자 이름과 일련 번호를 입력하면 프로그램이 GetDigltemTextA 함수를 호출하여 문자를 읽고 계산한 다음 마지막으로 lstremp 함수를 사용하여 비교합니다. 따라서 이러한 호출된 함수는 복호화 추적의 대상이 되며, 이러한 함수를 중단점으로 삼아 프로그램의 일련번호 검증 과정을 추적하면 정확한 일련번호를 찾을 수 있다. 암호 해독 기술을 연습하기 위해 특별히 제작된 이런 종류의 작은 프로그램을 일반적으로 "CrackMe"라고 합니다.

 2. 디버깅 대상 파일 로드

OllyDbg가 프로그램의 진입점에서 인터럽트를 하기 위해서는 프로그램을 불러오기 전에 해당 설정을 해야 합니다. OlyDbg를 실행하고 "Oplions" - "디버깅 옵션" 옵션을 클릭하여 디버깅 옵션 구성 대화 상자를 엽니다. 인터럽트 진입점, 모듈 로드/언로딩, 스레드 생성/종료 등과 같은 이벤트에 대한 OllyDhg의 처리 방법을 설정하려면 "이벤트" 탭을 클릭하십시오. 일반적으로 중단점은 "WinMain"에만 설정하면 됩니다
.

설정이 완료되면 "파일" - "열기" 옵션을 클릭하여 TraceMeexe를 엽니다. 이때 0llyDbg는 TraceMe의 첫 번째 명령에서 디버거 분석 코드를 중단하고 사용자의 다음 작업을 기다립니다. 아래 그림과 같이 004013AOh에서 커서가 멈추면 004013A0h가 프로그램의 진입점(EntryPoint)입니다. 대부분의 프로그램은 시작할 때 진입점에서 멈춥니다. 일부 특수 수정 방법을 통해 일부 프로그램은 시작할 때 인구 지점에서 멈출 수 없으므로 디버깅 방지 목적을 달성합니다. 코드 각 부분의 의미는 다음과 같습니다.

  • 가상 주소: 일반적으로 동일한 프로그램의 동일한 명령어는 다른 시스템 환경에서 동일한 값을 갖습니다.
  • 머신 코드: CPU가 실행하는 머신 코드입니다.
  • 조립 명령: 기계 코드에 해당하는 프로그램 코드

 레지스터 패널에는 각 레지스터의 현재 값이 표시됩니다. 레지스터에는 EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, EIP 등이 있으며, 아래 그림과 같이 총칭하여 32비트 레지스터라고 합니다. ESP는 포인터이며 스택의 값은 OllyDbg 인터페이스의 오른쪽 하단에 있는 스택 패널에 표시됩니다. 또 다른 중요한 레지스터는 실행될 현재 명령어를 가리키는 EIP입니다. "F7" 키를 누르면 명령어가 실행되고 EIP는 실행될 다음 명령어를 가리킵니다.

디버깅할 때 이러한 레지스터를 두 번 클릭하여 레지스터의 값을 수정할 수 있습니다. 그러나 EIP 레지스터는 직접 수정할 수 없으므로 004013AAh와 같은 디스어셈블리 창에서 새 명령어 시작 주소를 선택하고 마우스 오른쪽 버튼으로 클릭하고 팝업 바로 가기 메뉴에서 "New origin here"를 선택해야 합니다(여기는 새로운 EIP 옵션 EIP의 값은 4013AAh가 되고 프로그램은 이 명령에서 실행을 시작합니다 레지스터 아래에는 C, P, A, ZS, T, D, 0 및 해당 값인 플래그 레지스터가 있습니다. 두 개의 디지털 값 -0과 1만 될 수 있습니다. 숫자를 두 번 클릭하면 0과 1 사이를 전환할 수 있습니다.

 3. 단일 단계 추적

디버거의 가장 기본적인 기능 중 하나는 동적 추적입니다. 0llyDbg는 "디버그" 메뉴에서 실행 중인 명령을 제어하며 각 메뉴 항목에는 해당 단축키가 있습니다. olyDhg의 단일 단계 추적 단축키는 아래 그림과 같습니다.

단축키 기능
F7 호출 지시가 있을 때 단계별로 후속 조치
F8 차근차근, 호출 지시를 만났을 때 지나가고, 후속 조치를 취하지 마십시오.
Ctrl+F9 RER 명령이 발생할 때까지 중단
Alt+F9 시스템의 공역에 진입하면 이 명령은 즉시 응용 프로그램의 공역으로 돌아갈 수 있습니다.
F9 프로그램을 실행
F2 중단점 설정

"F8" 키는 디버깅에 자주 사용됩니다. 조립 명령을 문장 단위로, 단계별로 실행할 수 있습니다. 호출 명령을 만나면 후속 조치를 취하지 않고 통과합니다. 예는 다음과 같습니다.

 "F7" 키와 "F8" 키의 주요 차이점은 callloop와 같은 명령이 발생하면 "F8" 키를 눌러 통과하고 "F7 키를 눌러 후속 작업을 수행한다는 것입니다. 예를 들면 다음과 같습니다. 다음과 같습니다.

"call00401DA0"은 00401DAOh에서 서브루틴을 호출한다는 의미입니다. 서브루틴이 호출되면 호출이 가리키는 다음 명령문인 004013FFh로 리턴됩니다. "F7" 키를 눌러 00401DA에서 서브루틴을 추적합니다아, 상황을 관찰하면 그림 28과 같이 호출 명령의 다음 명령의 주소 004013FFh가 리턴 주소로 스택에 푸시되는 것을 알 수 있습니다. 서브루틴의 끝에는 00401DD7h에서 명령을 실행하고 호출이 가리키는 다음 명령문 004013FFh로 돌아가는 ret 명령이 있습니다. 서브루틴을 입력하는 과정에서 이전에 싱글스텝 추적했던 코드를 다시 보고 싶으면 "-"(빼기 기호) 키를 ​​누르면 되고, 커서를 가리키는 문장으로 되돌리려면 현재 EIP로 C 버튼을 클릭하거나 EIP 레지스터를 두 번 클릭합니다.


"F7" 또는 "F8" 키를 반복적으로 누르면 OllyDbg는 사용자 가  "Esc" 키, "F12" 키를 누르거나 중지할 다른 중단점을 만날 때까지 "Ctl+F7" 및 "Ctrl+F8" 단축키를 제공합니다. call finger에 있고 cl finger가 호출된 위치로 돌아가고 싶다면 단축키 "Ctrl+F9"를 눌러 Executetillreum"(execute to return) 명령을 실행할 수 있습니다. OllyDhg는 첫 번째 복귀에서 중지합니다. 명령이 발생했습니다(retretf 또는 iret) 이것은 쓸모없는 코드를 쉽게 건너뛸 수 있습니다.

 예를 들어 위의 코드가 00401DAO에 있을 때 "Ctl+F9" 단축키를 누르면 004013FFh로 돌아갑니다. et finger를 만났을 때 일시정지할지 통과할지 여부는 옵션에서 설정할 수 있는데, 방법은 디버그 설정 옵션 대화상자를 열고 "Trace" 탭에서 "After Execting tillRETstepover RET"를 설정하는 것입니다(ret 명령어 실행 후, ret 명령을 통해 단계) .
시스템 DLL에서 제공하는 API 기능을 입력한 경우 응용 프로그램의 영공으로 돌아가고 싶을 때 바로 가기 키 "Alt+F9"를 눌러 "Executetillusercode"(사용자 코드 실행) 명령을 실행할 수 있습니다. 예는 다음과 같습니다.

 004013C6h에서 "F7" 키를 눌러 KERNEL32DLL 시스템을 추적합니다. 예제는 다음과 같습니다.

"7C8114AB" 등은 시스템 DLL이 위치한 주소 공간이며, 이때 단축키 "Alt+F9"를 누르면 응용프로그램 영공으로 돌아갑니다. 코드는 다음과 같습니다. 

 참고: 소위 "공역"은 실제로 특정 순간에 CPU의 CS:EIP가 가리키는 특정 코드 조각의 소유자를 나타냅니다.

단일 단계 추적을 원하지 않고 프로그램을 직접 실행하려면 "F9" 키를 누르거나 도구 모음에서 오른쪽 버튼을 클릭하십시오. 대상 프로그램을 다시 디버그하려면 "Ctrl+F2" 단축키를 누르면 OllyDhg가 디버그 프로세스를 종료하고 다시 로드합니다. 프로그램이 무한 루프에 들어가면 "F12" 키를 눌러 프로그램을 일시 중단할 수 있습니다.

4. 중단점 설정

중단점(Breakpoint)은 디버거의 중요한 기능으로 프로그램을 지정된 위치에서 중단시켜 편리하게 분석할 수 있습니다. 아래 그림과 같이 커서를 004013A5h로 이동하고 "F2" 키를 눌러 중단점을 설정하고 다시 "F2" 키를 눌러 중단점을 취소합니다. 중단점을 설정하려면 "Hexdump" 열에서 해당 줄을 두 번 클릭하고 중단점을 취소하려면 다시 두 번 클릭합니다.

 중단점을 설정한 후 "Alt+B" 단축키를 누르거나 B 버튼을 클릭하여 중단점 창을 열고 아래 그림과 같이 중단점 세부 정보를 봅니다. 하드웨어 중단점 이외의 중단점이 여기에 표시됩니다. 여기서 "항상"은 중단점이 활성화됨을 의미하고 "비활성화"는 중단점이 비활성화됨을 의미합니다. 스페이스바를 눌러 상태를 전환합니다. 이러한 중단점은 상황에 맞는 메뉴를 통해 관리할 수도 있습니다. 중단점을 삭제하는 단축키는 "Del" 키입니다.

 

00B2A5C8   .  E8 1BAA0000   call 路径修复.00B34FE8                       ; \路径修复.00B34FE8
00B2A5CD   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A5CE   .  B8 4D5A0000   mov eax,0x5A4D
00B2A5D3   .  66:3905 0000B>cmp word ptr ds:[0xB20000],ax
00B2A5DA   .  74 04         je short 路径修复.00B2A5E0
00B2A5DC   >  33DB          xor ebx,ebx
00B2A5DE   .  EB 33         jmp short 路径修复.00B2A613
00B2A5E0   >  A1 3C00B200   mov eax,dword ptr ds:[0xB2003C]
00B2A5E5   .  81B8 0000B200>cmp dword ptr ds:[eax+0xB20000],0x4550
00B2A5EF   .^ 75 EB         jnz short 路径修复.00B2A5DC
00B2A5F1   .  B9 0B010000   mov ecx,0x10B
00B2A5F6   .  66:3988 1800B>cmp word ptr ds:[eax+0xB20018],cx
00B2A5FD   .^ 75 DD         jnz short 路径修复.00B2A5DC
00B2A5FF   .  33DB          xor ebx,ebx
00B2A601   .  83B8 7400B200>cmp dword ptr ds:[eax+0xB20074],0xE
00B2A608   .  76 09         jbe short 路径修复.00B2A613
00B2A60A   .  3998 E800B200 cmp dword ptr ds:[eax+0xB200E8],ebx
00B2A610   .  0f95c3        setne bl
00B2A613   >  895D E4       mov dword ptr ss:[ebp-0x1C],ebx
00B2A616   .  E8 067C0000   call 路径修复.00B32221
00B2A61B   .  85C0          test eax,eax
00B2A61D   .  75 08         jnz short 路径修复.00B2A627
00B2A61F   .  6A 1C         push 0x1C
00B2A621   .  E8 DC000000   call 路径修复.00B2A702
00B2A626   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A627   >  E8 F4690000   call 路径修复.00B31020
00B2A62C   .  85C0          test eax,eax
00B2A62E   .  75 08         jnz short 路径修复.00B2A638
00B2A630   .  6A 10         push 0x10
00B2A632   .  E8 CB000000   call 路径修复.00B2A702
00B2A637   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A638   >  E8 94AA0000   call 路径修复.00B350D1
00B2A63D   .  8365 FC 00    and dword ptr ss:[ebp-0x4],0x0
00B2A641   .  E8 EE7E0000   call 路径修复.00B32534
00B2A646   .  85C0          test eax,eax
00B2A648   .  79 08         jns short 路径修复.00B2A652
00B2A64A   .  6A 1B         push 0x1B
00B2A64C   .  E8 B1000000   call 路径修复.00B2A702
00B2A651   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A652   >  FF15 3400B400 call dword ptr ds:[<&KERNEL32.GetCommand>; [GetCommandLineA
00B2A658   .  A3 C8DCB400   mov dword ptr ds:[0xB4DCC8],eax
00B2A65D   .  E8 AFAA0000   call 路径修复.00B35111
00B2A662   .  A3 4CBDB400   mov dword ptr ds:[0xB4BD4C],eax
00B2A667   .  E8 52A40000   call 路径修复.00B34ABE
00B2A66C   .  85C0          test eax,eax
00B2A66E   .  79 08         jns short 路径修复.00B2A678
00B2A670   .  6A 08         push 0x8
00B2A672   .  E8 6D820000   call 路径修复.00B328E4
00B2A677   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A678   >  E8 70A60000   call 路径修复.00B34CED
00B2A67D   .  85C0          test eax,eax
00B2A67F   .  79 08         jns short 路径修复.00B2A689
00B2A681   .  6A 09         push 0x9
00B2A683   .  E8 5C820000   call 路径修复.00B328E4
00B2A688   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A689   >  6A 01         push 0x1                                 ; /Arg1 = 00000001
00B2A68B   .  E8 8E820000   call 路径修复.00B3291E                       ; \路径修复.00B3291E
00B2A690   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A691   .  85C0          test eax,eax
00B2A693   .  74 07         je short 路径修复.00B2A69C
00B2A695   .  50            push eax
00B2A696   .  E8 49820000   call 路径修复.00B328E4
00B2A69B   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A69C   >  E8 FDAA0000   call 路径修复.00B3519E
00B2A6A1   .  56            push esi                                 ; /Arg4 = 00B2A5A8
00B2A6A2   .  50            push eax                                 ; |Arg3 = 010FFC98
00B2A6A3   .  6A 00         push 0x0                                 ; |Arg2 = 00000000
00B2A6A5   .  68 0000B200   push 路径修复.00B20000                       ; |Arg1 = 00B20000
00B2A6AA   .  E8 B1CBFFFF   call 路径修复.00B27260                       ; \路径修复.00B27260
00B2A6AF   .  8BF0          mov esi,eax
00B2A6B1   .  8975 DC       mov dword ptr ss:[ebp-0x24],esi          ;  路径修复.<ModuleEntryPoint>
00B2A6B4   .  85DB          test ebx,ebx
00B2A6B6   .  75 06         jnz short 路径修复.00B2A6BE
00B2A6B8   .  56            push esi                                 ;  路径修复.<ModuleEntryPoint>
00B2A6B9   .  E8 C9840000   call 路径修复.00B32B87
00B2A6BE   >  E8 4C820000   call 路径修复.00B3290F
00B2A6C3   .  EB 2E         jmp short 路径修复.00B2A6F3
00B2A6C5   .  8B4D EC       mov ecx,dword ptr ss:[ebp-0x14]
00B2A6C8   .  8B01          mov eax,dword ptr ds:[ecx]
00B2A6CA   .  8B00          mov eax,dword ptr ds:[eax]
00B2A6CC   .  8945 E0       mov dword ptr ss:[ebp-0x20],eax
00B2A6CF   .  51            push ecx                                 ;  路径修复.<ModuleEntryPoint>
00B2A6D0   .  50            push eax
00B2A6D1   .  E8 8DA20000   call 路径修复.00B34963
00B2A6D6   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A6D7   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A6D8   .  C3            retn
00B2A6D9   .  8B65 E8       mov esp,dword ptr ss:[ebp-0x18]
00B2A6DC   .  8B75 E0       mov esi,dword ptr ss:[ebp-0x20]
00B2A6DF   .  8975 DC       mov dword ptr ss:[ebp-0x24],esi          ;  路径修复.<ModuleEntryPoint>
00B2A6E2   .  837D E4 00    cmp dword ptr ss:[ebp-0x1C],0x0
00B2A6E6   .  75 06         jnz short 路径修复.00B2A6EE
00B2A6E8   .  56            push esi                                 ;  路径修复.<ModuleEntryPoint>
00B2A6E9   .  E8 B4820000   call 路径修复.00B329A2
00B2A6EE   >  E8 0D820000   call 路径修复.00B32900
00B2A6F3   >  C745 FC FEFFF>mov dword ptr ss:[ebp-0x4],-0x2
00B2A6FA   .  8BC6          mov eax,esi                              ;  路径修复.<ModuleEntryPoint>
00B2A6FC   .  E8 847C0000   call 路径修复.00B32385
00B2A701   .  C3            retn
00B2A702  /$  55            push ebp

5. 디버깅 분석

GetDlllemTextA 함수에서 나가려면 "F8" 키를 누르십시오. 물론 "Alt+F9" 단축키를 눌러 함수가 호출된 위치로 돌아갈 수도 있습니다. OllyDbg는 매우 강력합니다.각 함수의 호출 매개 변수와 현재 값에 주석을 달았습니다.관련 코드는 다음과 같습니다.

 이 코드를 읽을 때 염두에 두어야 할 몇 가지 사항이 있습니다.

  • 각 API 함수의 정의를 명확히 하세요. (해당 API 매뉴얼을 확인하세요.)
  • 대부분의 API 함수는 sdcall 호출 규칙을 채택합니다. 즉, 함수 모집단 매개변수는 오른쪽에서 왼쪽 순서로 스택에 배치되고 호출 수신자는 스택의 매개변수를 정리하고 반환 값은 eax 레지스터에 배치됩니다. . 따라서 해당 API 함수는 앞에 있는 푸시 명령어를 분석해야 하는데, 이 명령어는 API 호출로 전달될 파라미터를 스택에 넣는다. 전체 추적 프로세스 동안 스택 데이터의 변경 사항에 주의하십시오.
  • C 코드의 서브루틴은 C 호출 규칙을 채택하고 함수 모집단의 매개변수를 오른쪽에서 왼쪽 순서로 스택에 추가하고 호출자는 스택의 매개변수를 지웁니다.
  • 호출 규칙, 매개변수 전송 및 기타 지식인 GetDlgItemText 함수는 표준 호출 규칙을 사용하며 매개변수는 오른쪽에서 왼쪽 순서로 스택에 배치됩니다. 이 예제의 어셈블리 코드는 다음과 같습니다.
00B2A728  \.  C3            retn
00B2A729      CC            int3
00B2A72A      CC            int3
00B2A72B      CC            int3
00B2A72C      CC            int3
00B2A72D      CC            int3
00B2A72E      CC            int3
00B2A72F      CC            int3
00B2A730   $  57            push edi                                 ;  路径修复.<ModuleEntryPoint>
00B2A731   .  56            push esi                                 ;  路径修复.<ModuleEntryPoint>
00B2A732   .  8B7424 10     mov esi,dword ptr ss:[esp+0x10]          ;  ntdll.77C67B6E
00B2A736   .  8B4C24 14     mov ecx,dword ptr ss:[esp+0x14]
00B2A73A   .  8B7C24 0C     mov edi,dword ptr ss:[esp+0xC]
00B2A73E   .  8BC1          mov eax,ecx                              ;  路径修复.<ModuleEntryPoint>
00B2A740   .  8BD1          mov edx,ecx                              ;  路径修复.<ModuleEntryPoint>
00B2A742   .  03C6          add eax,esi                              ;  路径修复.<ModuleEntryPoint>

 

추천

출처blog.csdn.net/qq_22903531/article/details/131390235