前言
以前看过CC断点的检测原理.
今天做脱壳练习时, 居然看到cm中有一个fnMessageBox函数中进行了CC断点检测.
记录
cm中的实际函数
00FAF476 <fnMessageBoxEx> 55 push ebp
00FAF477 8BEC mov ebp, esp
00FAF479 51 push ecx
00FAF47A 53 push ebx
00FAF47B 56 push esi
00FAF47C 57 push edi
00FAF47D 60 pushad
00FAF47E 8B15 7420FE00 mov edx, dword ptr [FE2074] ; kernel32.7C8092CA
00FAF484 83C2 64 add edx, 64
00FAF487 FFD2 call edx ; getTickCount, but not used result
00FAF489 8B15 3020FE00 mov edx, dword ptr [FE2030] ; USER32.77D50786
00FAF48F 83C2 64 add edx, 64 ; MessageBox
00FAF492 B9 05000000 mov ecx, 5
00FAF497 803A CC cmp byte ptr [edx], 0CC
00FAF49A 74 10 je short <L_END> ; find CC breakpoint
00FAF49C ^ E2 F9 loopd short 00FAF497 ; check cc breakpoint 5 times
00FAF49E <L_CALL_ORG_FN> FF75 14 push dword ptr [ebp+14]
00FAF4A1 FF75 10 push dword ptr [ebp+10]
00FAF4A4 FF75 0C push dword ptr [ebp+C]
00FAF4A7 FF75 08 push dword ptr [ebp+8]
00FAF4AA FFD2 call edx ; call org MessageBox
00FAF4AC <L_END> 8945 FC mov dword ptr [ebp-4], eax ; [ebp - 4] is local value iRc
00FAF4AF 61 popad
00FAF4B0 8B45 FC mov eax, dword ptr [ebp-4]
00FAF4B3 5F pop edi
00FAF4B4 5E pop esi
00FAF4B5 5B pop ebx
00FAF4B6 C9 leave
00FAF4B7 C2 1000 retn 10
还原的CC断点检测
// CheckCcBp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <CONIO.H>
int __stdcall MessageBoxA_ByAntiDebug( IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType);
typedef int (__stdcall * PFN_MessageBoxA)( IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType);
#define API_INDEX_MessageBox 0
#define KEY_dwAryOrgApiAddr 0x64
DWORD g_dwAryOrgApiAddr[1] = {0};
int main(int argc, char* argv[])
{
HMODULE hDll = NULL;
PFN_MessageBoxA pfnMessageBox = NULL;
// 先保存原始api地址, 这里模拟一下, 不要求和cm中相同
hDll = LoadLibraryA("user32.dll");
g_dwAryOrgApiAddr[API_INDEX_MessageBox] = (DWORD)GetProcAddress(hDll, "MessageBoxA") - KEY_dwAryOrgApiAddr;
// MessageBoxA入口被下了CC断点时, 就不执行原始函数
MessageBoxA_ByAntiDebug(NULL, NULL, NULL, NULL);
system("pause");
return 0;
}
int __stdcall MessageBoxA_ByAntiDebug( IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType)
{
int iRc = 0;
DWORD dwFunAddr = g_dwAryOrgApiAddr[API_INDEX_MessageBox] + KEY_dwAryOrgApiAddr;
if (0xcc != *(BYTE*)(dwFunAddr)) {
iRc = ((PFN_MessageBoxA)dwFunAddr)(hWnd, lpText, lpCaption, uType);
}
return iRc;
}
/** cm's cc breeakpoint check
00FAF476 <fnMessageBoxEx> 55 push ebp
00FAF477 8BEC mov ebp, esp
00FAF479 51 push ecx
00FAF47A 53 push ebx
00FAF47B 56 push esi
00FAF47C 57 push edi
00FAF47D 60 pushad
00FAF47E 8B15 7420FE00 mov edx, dword ptr [FE2074] ; kernel32.7C8092CA
00FAF484 83C2 64 add edx, 64
00FAF487 FFD2 call edx ; getTickCount, but not used result
00FAF489 8B15 3020FE00 mov edx, dword ptr [FE2030] ; USER32.77D50786
00FAF48F 83C2 64 add edx, 64 ; MessageBox
00FAF492 B9 05000000 mov ecx, 5
00FAF497 803A CC cmp byte ptr [edx], 0CC
00FAF49A 74 10 je short <L_END> ; find CC breakpoint
00FAF49C ^ E2 F9 loopd short 00FAF497 ; check cc breakpoint 5 times
00FAF49E <L_CALL_ORG_FN> FF75 14 push dword ptr [ebp+14]
00FAF4A1 FF75 10 push dword ptr [ebp+10]
00FAF4A4 FF75 0C push dword ptr [ebp+C]
00FAF4A7 FF75 08 push dword ptr [ebp+8]
00FAF4AA FFD2 call edx ; call org MessageBox
00FAF4AC <L_END> 8945 FC mov dword ptr [ebp-4], eax ; [ebp - 4] is local value iRc
00FAF4AF 61 popad
00FAF4B0 8B45 FC mov eax, dword ptr [ebp-4]
00FAF4B3 5F pop edi
00FAF4B4 5E pop esi
00FAF4B5 5B pop ebx
00FAF4B6 C9 leave
00FAF4B7 C2 1000 retn 10
*/