破解過程及方法.

我們知道一般的鎖KEY , 或是一定是用hook 將原WIN API 攔劫, 先導到自己的程式後才還給系統, 或直接retun.這時原功能就無效了.例如有些保護軟體為了不讓人copy/paste 或hardcopy(prt scr sysrq/print screen) 沒有作用,常用的手法, 或我們如何繞過它?

#想法:

  1. 如果我們可以完整執行原 API 就不受HOOK影響.

  2. 如果我們可以知道原 API 進入點, 也許就辦得到

 @ 但如果保護用hook, 問題2其實沒有被改過. API 的進入點是跟原來一樣, 所以想法改問3.

  3. 如果我們可以知道原 API 的開頭 machine code 是什麼, 也許就可以還原.

看一下 SYS DLL API 的 PSEUDO code

進入點: 

1. push important registers

2. change stack register to local using structure

3. initial local variables

4. main program.... 

Hook 會做什麼事.....

會將 A. 將1. 改為 jump to my_entry_point , B. 做他要保護的事, C. 可能再跳回2.接著執行其餘未完成的工作.

 //----------------------------------------------------------------------------------------------------

//the capturedemo is download from web, Search CaptureDemo_sln you will find the project

unsigned int xxx=(unsigned int ) ::BitBlt;

/*****************************************************************************************

Function: CScreenImage::CaptureRect
Purpose: captures a screen rectangle
Parameters: rect: screen rectangle to be captured
Return: non-zero value if successful
****************************************************************************************/
BOOL CScreenImage::CaptureRect(const CRect& rect)
{
// detach and destroy the old bitmap if any attached
// DWORD PID;
DWORD PID = ::GetCurrentProcessId();
// HWND targetWnd = FindWindow("Afx:013B0000:b:00010003:00000006:002006B3", "未命名 - CaptureDemo");
// GetWindowThreadProcessId(targetWnd, &PID);
// return PID;

// HA1NDLE hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)0x5AC);
HANDLE hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false, PID);
// hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)pe32.th32ProcessID);
DWORD dwNumberOfBytesRead=1;
char tmp=0x55;
char temp[]={0x8b,0xff,0x55,0x8b,0xec};
int i;

for (i=0;i<5;i++)
{
 // if(!::WriteProcessMemory(hProcess,(LPVOID)(xxx+i),&temp[i],1,&dwNumberOfBytesRead))
  {
  }
}
if (hProcess)
CloseHandle(hProcess);

static int cnt=0;

CImage::Destroy();

// create a screen and a memory device context
HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
// create a compatible bitmap and select it in the memory DC
HBITMAP hBitmap =
::CreateCompatibleBitmap(hDCScreen, rect.Width(), rect.Height());
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);

// bit-blit from screen to memory device context
// note: CAPTUREBLT flag is required to capture layered windows
DWORD dwRop = SRCCOPY | CAPTUREBLT;
unsigned int xxx=(unsigned int ) ::BitBlt;
BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(),
hDCScreen,
rect.left, rect.top, dwRop);
// attach bitmap handle to this object
Attach(hBitmap);
CString str=L"g:\\Cap_0";
str.Format(L"%s%d%s",str,cnt,L".bmp");
// LPCTSTR sss=L"g:\\aaxxzzaa.bmp";
LPCTSTR sss=(str);
SaveToFile(hBitmap, sss);
// restore the memory DC and perform cleanup
::SelectObject(hDCMem, hBmpOld);
::DeleteDC(hDCMem);
::DeleteDC(hDCScreen);
cnt++;
return bRet;
}

====================================

找到demo capture, 用 VS開啟, 

在BitBlt 那行設下斷點, 按下 F5 go, menu 進入capture/screen

BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(), 
hDCScreen, rect.left, rect.top, dwRop);

會停在斷點, 

接著 按右鍵移至反組譯碼,
按 f10,.... 直到停在這行,00358B13 mov esi,esp
00358B15 mov eax,dword ptr [ebp-94h]
00358B1B push eax
00358B1C mov ecx,dword ptr [ebp+8]
00358B1F mov edx,dword ptr [ecx+4]
00358B22 push edx
00358B23 mov eax,dword ptr [ebp+8]
00358B26 mov ecx,dword ptr [eax]
00358B28 push ecx
00358B29 mov edx,dword ptr [ebp-64h]
00358B2C push edx
00358B2D mov ecx,dword ptr [ebp+8]
00358B30 call CRect::Height (35202Ch)
00358B35 push eax
00358B36 mov ecx,dword ptr [ebp+8]
00358B39 call CRect::Width (3514A6h)
00358B3E push eax
00358B3F push 0
00358B41 push 0
00358B43 mov eax,dword ptr [ebp-70h]
00358B46 push eax

停在這行, 按下F11
-> 00358B47 call dword ptr [__imp__BitBlt@36 (36FC2Ch)]
00358B4D cmp esi,esp
00358B4F call @ILT+3175(__RTC_CheckEsp) (351C6Ch)
00358B54 mov dword ptr [ebp-0ACh],eax接著 按F11 進入

... BITBLT 原來正常的進入點 

75D65EA6 mov edi,edi
75D65EA8 push ebp
75D65EA9 mov ebp,esp
75D65EAB push ecx
75D65EAC mov eax,dword ptr [ebp+28h]
75D65EAF mov ecx,eax
75D65EB1 shl ecx,2
75D65EB4 xor ecx,eax
75D65EB6 test ecx,0CC0000h
75D65EBC je 75D768DB
75D65EC2 push ebx
75D65EC3 mov ebx,dword ptr [ebp+8]
75D65EC6 push esi
75D65EC7 xor esi,esi
75D65EC9 push edi
75D65ECA mov edi,10000h
75D65ECF cmp dword ptr ds:[75DB0C88h],esi

在 [偵錯] 功能表上,按一下 [Windows],然後按一下 [記憶體]。
在位址上輸入BITBLT 進入點:75D65EA6 按下enter

memory dump

0x75D65EA6 8b ff 55 8b ec 51 8b 45 28 8b c8 c1 e1 02 33 c8 f7 c1 00 00 cc 00 0f 84 19 ....

0x75D65EDC  c3 25 00 00 7f 00 3b c7 0f 85 b3 e5 01 00 56 64 a1 18 00 00 00 

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

啟動保護程式, 發現print screen 已不能使用.

重覆上面的步驟.

--------------- 進入點變成如此.
75D65EA6 jmp 10007CC0
75D65EAB push ecx
75D65EAC mov eax,dword ptr [ebp+28h]
75D65EAF mov ecx,eax
75D65EB1 shl ecx,2
75D65EB4 xor ecx,eax
75D65EB6 test ecx,0CC0000h
75D65EBC je 75D768DB
75D65EC2 push ebx
75D65EC3 mov ebx,dword ptr [ebp+8]
75D65EC6 push esi
75D65EC7 xor esi,esi
75D65EC9 push edi
75D65ECA mov edi,10000h
75D65ECF cmp dword ptr ds:[75DB0C88h],esi

memory dump

0x75D65EA6  e9 15 1e 2a 9a 51 8b 45 28 8b c8 c1 e1 02 33 c8 f7 c1 00 00 cc 0

0x75D65EDC  c3 25 00 00 7f 00 3b c7 0f 85 b3 e5 01 00 56 64 a1 18 0

; 跟原來比較發現有5個byte 被改掉. 有顏色的5個BYTE

所以如果可以將這5個byte 還原, 就可以破解.

變數 temp[] 就是這5 個bytes, 

  if(!::WriteProcessMemory(hProcess,(LPVOID)(xxx+i),&temp[i],1,&dwNumberOfBytesRead))
 mark 掉的這一行打開.

重新編譯, 及執行 capture->screen . 真的捉下螢幕了.

#

arrow
arrow
    全站熱搜

    cianfen 發表在 痞客邦 留言(1) 人氣()