2012年5月4日 星期五

總結一下得到內核模組位址的方法

網上說的比較常見的4種方法:

1、通過DriverEntry傳入的DriverObject參數的DriverSection成員指向LDR_DATA_TABLE_ENTRY結構,通過遍歷這張表得到ntoskrnl的基址和大小

2ZwQuerySystemInformation大法

3、搜索記憶體 

4、利用KPCR結構

存在的問題:

1、第1種方法和第4種方法得到的結果比ZwQuerySystemInformation少一個

2、第1種方法如果輸出BaseDllNamentoskrnl.exe,如果輸出FullDllName則是:\WINDOWS\system32\ntkrnlpa.exe,位址都是:804d8000,不明白為何

環境:虛擬機器VMWareWIN XP SP3  + WDK ---- WINXP Check方式編譯


#include <ntddk.h>
//---------------------------------//
//下面的結構包含了一些重要資訊。如:PsLoadedModuleList ,它是Windows載入的所有內核模組構成的鏈表的表頭。
//PsLoadedModuleList就是如下這個結構體中InLoadOrderLinks。即為LDR_DATA_TABLE_ENTRY結構的第一項。
#pragma pack(push)//結構定義
#pragma pack(1)                  
typedef struct _LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY         InLoadOrderLinks;
    LIST_ENTRY         InMemoryOrderLinks;
    LIST_ENTRY         InInitializationOrderLinks;
    PVOID              DllBase;
    PVOID              EntryPoint;
    ULONG              SizeOfImage;
    UNICODE_STRING     FullDllName;
    UNICODE_STRING     BaseDllName;
    ULONG              Flags;
    USHORT             LoadCount;
    USHORT             TlsIndex;
    union
    {
        LIST_ENTRY     HashLinks;
        struct
        {
            PVOID      SectionPointer;
            ULONG      CheckSum;
        };
    };
    union
    {
        ULONG           TimeDateStamp;
        PVOID           LoadedImports;
    };
    PVOID               EntryPointActivationContext;
    PVOID               PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
#pragma pack(pop)
//---------------------------------------------------------------------------------------------------//函式宣告
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath);
NTSTATUS DriverUnload();
//Method3用到,指定當前執行緒運行在那個處理器
NTKERNELAPI VOID KeSetSystemAffinityThread ( KAFFINITY Affinity );
NTKERNELAPI VOID KeRevertToUserAffinityThread ( VOID );

NTKERNELAPI NTSTATUS ZwQuerySystemInformation(
                                            IN ULONG SystemInformationClass,
                                              IN OUT PVOID SystemInformation,
                                              IN ULONG SystemInformationLength,
                                              IN PULONG ReturnLength OPTIONAL 
                        );

#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DriverUnload)
//---------------------------------------------------------------------------------------------------//變數、常量、結構定義
UNICODE_STRING BaseName;

#define SystemModuleInformation 11  //Method2要用到11功能號

typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY
{
  ULONG   Unknow1;
  ULONG   Unknow2;
  #ifdef  _WIN64
  ULONG   Unknow3;
  ULONG   Unknow4:
  #endif
  PVOID   Base;
  ULONG   Size;
  ULONG   Flags;
  USHORT  Index;
  USHORT  NameLength;
  USHORT  LoadCount;
  USHORT  ModuleNameOffset;
  char    ImageName[256];
}SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;

typedef struct _SYSTEM_MODULE_INFORMATION
{
   ULONG Count;//內核中以載入的模組的個數
   SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
}SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;


//---------------------------------------------------------------------------------------------------//
/*
    用到了DriverObject域的InLoadOrderLinks鏈表

注意:
   下面的代碼會用到一個宏:
---------------------------------------------------------------------------------------------------------------------
CONTAINING_RECORD 這樣的一個宏,它的定義如下:
#define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type*)0)->field)))

根據網上資料:就是address -(fieldtype中的偏移)
----------------------------------------------------------------------------------------------------------------------
*/
VOID Method1(IN PDRIVER_OBJECT DriverObject)//遍歷鏈表
{
  ULONG Base=0;//模組基底位址
  LDR_DATA_TABLE_ENTRY* SectionBase=NULL;
  LIST_ENTRY* Entry=NULL;
    LIST_ENTRY InLoadOrderLinks;
    ULONG num=0;
  Entry=((LIST_ENTRY*)DriverObject->DriverSection)->Flink;

  do
  {
    SectionBase=CONTAINING_RECORD(Entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);//得到這個Entry所屬的Section的地址,此方法經過驗證可行

      if (SectionBase->EntryPoint && 
            SectionBase->BaseDllName.Buffer &&
            SectionBase->FullDllName.Buffer && 
            SectionBase->LoadCount
            )
    {
      DbgPrint("方法一遍歷模組名稱:%wZ,地址:%x\n",&(SectionBase->FullDllName),SectionBase->DllBase);
      //DbgPrint("方法一遍歷模組名稱:%wZ,地址:%8X\n",&(SectionBase->BaseDllName),SectionBase->DllBase);
      num++;
      /*if(!RtlCompareUnicodeString(&(SectionBase->BaseDllName),&BaseName,FALSE))
      {
        DbgPrint("方法一模組名稱:%wZ,地址:%x\n",&(SectionBase->BaseDllName),SectionBase->DllBase);
      }*/
    }
    Entry=Entry->Flink;
    
  }while(Entry!=((LIST_ENTRY*)DriverObject->DriverSection)->Flink);//直到遍歷回來
  DbgPrint("方法一得到模組總數:%d\n",num);
}

void Method2()//ZwQuerySystemInformation大法
{
  PVOID pBuffer=0;//緩衝區
  NTSTATUS Result;//查詢結果
  ULONG NeedSize;
  PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;//將結果強制轉換為該類型
  ULONG BufferSize = 0x5000;//初始分配記憶體大小,沒有採用查詢再分配的迴圈方法
  ULONG ModuleCount;//模組總數
  ULONG i;
  do
  {
    pBuffer=ExAllocatePool(NonPagedPool,BufferSize);
    if(pBuffer==NULL)
    {
      DbgPrint("分配記憶體失敗!\n");
      return FALSE;
    }
    Result=ZwQuerySystemInformation(SystemModuleInformation,pBuffer,BufferSize,&NeedSize);
    if(Result==STATUS_INFO_LENGTH_MISMATCH )//分配不夠
    {
      ExFreePool(pBuffer);
      //大小乘以2,重新分配
      BufferSize*=2;
    }
    else if(!NT_SUCCESS(Result))//失敗,放棄吧
    {
      DbgPrint( "查詢失敗,錯誤碼:%8X\n", Result );
      ExFreePool(pBuffer);
      return FALSE;
    }
   }while( Result == STATUS_INFO_LENGTH_MISMATCH );

  pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)pBuffer;//類型轉換
  ModuleCount=pSystemModuleInformation->Count;//模組總數
  for(i=0;i<ModuleCount;i++)
  {
    DbgPrint( "方法二遍歷模組名稱:%s,地址:%8X\n", pSystemModuleInformation->Module[i].ImageName, pSystemModuleInformation->Module[i].Base );
  }
  DbgPrint("方法二得到模組總數:%d\n",ModuleCount);
  ExFreePool(pBuffer);
  return TRUE;
}
VOID Method3(ULONG Base)//搜索記憶體,從0x80000000-----0xa0000000
{
  ;
}
//內核中FS寄存器指向KPCR結構,每個處理器都有一個,使用第一個處理器即可其中比較重要的是KdVersionBlock這個指標它指向一個DBGKD_GET_VERSION64這個結構.

//這個結構體裡面包含了一些重要資訊。如:PsLoadedModuleList ,它是Windows載入的所有內核模組構成的鏈表的表頭

//兩個處理器對應的KPCR結構是有區別的只有第一個處理器的KPCRKdVersionBlock才指向DBGKD_GET_VERSION64這個結構.

//-------------------------------------仔細觀察定義會發現,這個跟使用DriverObject方法達到的鏈表示一樣的!
void Method4()                              
{
  ULONG Addr;//內核地址

  LIST_ENTRY* Entry=NULL;
    LIST_ENTRY InLoadOrderLinks;
  LDR_DATA_TABLE_ENTRY* SectionBase=NULL;//LdrData->DllBase,LdrData->FullDllNme

    ULONG num=0;
    //-----------------------------------------------------------------------------//在莫灰灰基礎上修改一小部分
    KeSetSystemAffinityThread(1);//使當前執行緒運行在第一個處理器上
  _asm
  {
    push  eax
    mov   eax,FS:[0x34]                     ;指向KdVersionBlock的指標
    add   eax,18h                           ;得到指向PsLoadedModuleList的地址,即該指標的地址,指針裡存有PsLoadedModuleList的地址
    mov   eax,[eax]                         ;得到PsLoadedModuleList的地址
        mov   eax,[eax]                         ;得到PsLoadedModuleList的內容
    //mov   eax,[eax+18h]                     ;取出DllBase, ntoskrnl.exe的基底位址
        mov   Addr,eax
        pop  eax
  }
  
  KeRevertToUserAffinityThread();//恢復執行緒運行的處理器
  //----------------------------------------------------------------------// 以下跟方法一重複

    Entry=(LIST_ENTRY*)Addr;

  do
  {
    SectionBase=CONTAINING_RECORD(Entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);//得到這個Entry所屬的Section的地址,此方法經過驗證可行

      if (SectionBase->EntryPoint && 
            SectionBase->BaseDllName.Buffer &&
            SectionBase->FullDllName.Buffer &&
            SectionBase->LoadCount
            )
    {
      DbgPrint("方法四遍歷模組名稱:%wZ,地址:%8X\n",&(SectionBase->FullDllName),SectionBase->DllBase);
      num++;
    }
    Entry=Entry->Flink;
    
  }while(Entry!=(LIST_ENTRY*)Addr);//直到遍歷回來
  DbgPrint("方法四得到模組總數:%d\n",num);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
{
  ULONG EntryAddr;
  _asm
  {
    push ecx;
    lea ecx,[ebp][4];//得到DriverEntry返回地址
    mov EntryAddr,ecx;
    pop ecx;
  }
  EntryAddr=*(ULONG*)EntryAddr;
  DbgPrint("驅動返回地址:%8X\n",EntryAddr);
  RtlInitUnicodeString(&BaseName,L"ntoskrnl.exe");
  DbgPrint("驅動載入成功!\n");
  //-------------------------------//
  Method1(pDriverObject);
  //-------------------------------//
  Method2();
       //-------------------------------//
  Method3();
        //-------------------------------//
  Method4();
  //-------------------------------//
  pDriverObject->DriverUnload=DriverUnload;
  return STATUS_SUCCESS;
}
NTSTATUS DriverUnload()
{
  DbgPrint("驅動卸載成功\n");
}




2011年10月19日 星期三

[分享]Win 7下定位kernel32.dll基址及shellcode編寫


      為了使shellcode在多種作業系統平臺下都可以正常運行,就不得不動態的定位kernel32.dll的基底位址。而被廣泛使用的一種方法是通過TEB/PEB結構獲取kernel32.dll基底位址,我個人第一次接觸是通過綠盟月刊的一篇文章“通過TEB/PEB枚舉當前進程空間中使用者模組清單”方才知道這種被眾多程式設計人員使用的方法。至於這個方法的最原始出處該文作者也未提及。只得知29A雜誌也有大量使用該技術。這種方法適用於除Win7以外的所有windows作業系統包括95/98/ME/NT/2K/XP,大小只有34 bytes,下面是其原理及實現代碼;
      更詳細的知識大家可以參考snowdbg大牛的文章Windows下的shellcode剖析淺談http://bbs.pediy.com/showthread.php?t=99007
      利用PEB結構來查找kernel32.dll的原理:FS段寄存器作為選擇子指向當前的TEB結構,在TEB偏移0x30處是PEB指標。而在PEB偏移的0x0c處是指向PEB_LDR_DATA結構的指標,位於PEB_LDR_DATA結構偏移0x1c處,是一個叫InInitialzationOrderModuleList的成員,他是指向LDR_MODULE鏈表結構中,相應的雙向鏈表頭部的指標,該鏈表載入的DLL的順序是ntdll.dllkernel32.dl,因此該成員所指的鏈表偏移0x08處為kernel32.dll地址。
更詳細的知識大家可以參考snowdbg大牛的文章Windows下的shellcode剖析淺談http://bbs.pediy.com/showthread.php?t=99007
獲取KERNEL32.DLL基址彙編實現代碼:

;find kernel32.dll
find_kernel32:
    push esi
    xor eax, eax
    mov eax, [fs:eax+0x30]
    test eax, eax
    js find_kernel32_9x        ;win9x or nt
find_kernel32_nt:
    mov eax, [eax + 0x0c]
    mov esi, [eax + 0x1c]
    lodsd
    mov eax, [eax + 0x8]
    jmp find_kernel32_finished
find_kernel32_9x:
    mov eax, [eax + 0x34]
    lea eax, [eax + 0x7c]
    mov eax, [eax + 0x3c]
find_kernel32_finished:
    pop esi
    ret

但非常可惜的是這種方法在Win7下是不適用的,所以很高興現在給大家分享國外網站上看到的一種新的方法來定位kernel32.dl的基底位址,該方法可以在所有windows版本上適用!這種方法通過在InInitializationOrderModuleList中查找kernel32.dll模組名稱的長度來定位它的基底位址,因為"kernel32.dll"的最後一個字元為"\0"結束符。所以倘若模組最後一個位元組為"\0"即可定位kernel32.dll的地址;

具體代碼實現方法:
;find kernel32.dll
find_kernel32:
    push esi
    xor ecx, ecx
    mov esi, [fs:ecx+0x30]
    mov esi, [esi + 0x0c]
    mov esi, [esi + 0x1c]
next_module:
    mov eax, [esi + 0x8]
    mov edi,[esi+0x20]
    mov esi ,[esi]
    cmp [edi+12*2],cx
    jne next_module
    pop esi
    Ret
      通過我的測試,這種利用該方法編寫的shellcode可以在32位平臺Windows 5.0-7.0的所有版本上適用,下面是經我測試在win 7下實現執行calc.exeshellcodeshellcode本身寫的很粗糙只為驗證該方法的可用性!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
  unsigned char shellcode[219] = {
  0xE9, 0x96, 0x00, 0x00, 0x00, 0x56, 0x31, 0xC9, 0x64, 0x8B, 0x71, 0x30, 0x8B, 0x76, 0x0C, 0x8B, 
  0x76, 0x1C, 0x8B, 0x46, 0x08, 0x8B, 0x7E, 0x20, 0x8B, 0x36, 0x66, 0x39, 0x4F, 0x18, 0x75, 0xF2, 
  0x5E, 0xC3, 0x60, 0x8B, 0x6C, 0x24, 0x24, 0x8B, 0x45, 0x3C, 0x8B, 0x54, 0x05, 0x78, 0x01, 0xEA, 
  0x8B, 0x4A, 0x18, 0x8B, 0x5A, 0x20, 0x01, 0xEB, 0xE3, 0x37, 0x49, 0x8B, 0x34, 0x8B, 0x01, 0xEE, 
  0x31, 0xFF, 0x31, 0xC0, 0xFC, 0xAC, 0x84, 0xC0, 0x74, 0x0A, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE9, 
  0xF1, 0xFF, 0xFF, 0xFF, 0x3B, 0x7C, 0x24, 0x28, 0x75, 0xDE, 0x8B, 0x5A, 0x24, 0x01, 0xEB, 0x66, 
  0x8B, 0x0C, 0x4B, 0x8B, 0x5A, 0x1C, 0x01, 0xEB, 0x8B, 0x04, 0x8B, 0x01, 0xE8, 0x89, 0x44, 0x24, 
  0x1C, 0x61, 0xC3, 0xAD, 0x50, 0x52, 0xE8, 0xA7, 0xFF, 0xFF, 0xFF, 0x89, 0x07, 0x81, 0xC4, 0x08, 
  0x00, 0x00, 0x00, 0x81, 0xC7, 0x04, 0x00, 0x00, 0x00, 0x39, 0xCE, 0x75, 0xE6, 0xC3, 0xE8, 0x19, 
  0x00, 0x00, 0x00, 0x98, 0xFE, 0x8A, 0x0E, 0x7E, 0xD8, 0xE2, 0x73, 0x81, 0xEC, 0x08, 0x00, 0x00, 
  0x00, 0x89, 0xE5, 0xE8, 0x5D, 0xFF, 0xFF, 0xFF, 0x89, 0xC2, 0xEB, 0xE2, 0x5E, 0x8D, 0x7D, 0x04, 
  0x89, 0xF1, 0x81, 0xC1, 0x08, 0x00, 0x00, 0x00, 0xE8, 0xB6, 0xFF, 0xFF, 0xFF, 0xEB, 0x0E, 0x5B, 
  0x31, 0xC0, 0x50, 0x53, 0xFF, 0x55, 0x04, 0x31, 0xC0, 0x50, 0xFF, 0x55, 0x08, 0xE8, 0xED, 0xFF, 
  0xFF, 0xFF, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65, 0x00
};

printf("size of shellcode: %d\n", strlen(shellcode));
system("pause");
((void (*)())shellcode)();
return 0;
}
感謝所有朋友回復和意見以及riusksk的驗證,漏洞方面我是新手,還需不斷學習,我深信技術的提升總是通過一次一次的更新的認知!發現自己的不足,不斷進步!這才是我一直關注看雪的原因!
參考連結:
http://skypher.com/index.php/2009/07/22/shellcode-finding-kernel32-in-windows-7/
http://code.google.com/p/w32-exec-calc-shellcode/


 


 


 


---------------------------另種獲得kernel32.dll基址方式---------------------------


 


自己實現的,直接比對模組名得到kernel32.dll基底位址,原理一樣,適用所有windows版本
            MOV  EAX,DWORD PTR FS:[30H]  
            MOV  EAX,DWORD PTR [EAX+0CH]
        MOV  EAX,DWORD PTR [EAX+1CH] 
//...................................................................................................


            PUSH 0x006c006c      
            PUSH 0x0064002e
            PUSH 0x00320033
            PUSH 0x006c0065
            PUSH 0x006e0072
            PUSH 0x0065006B            
            MOV ESI,ESP
            
_LOOP:           
            XOR ECX,ECX
            MOV EAX,DWORD PTR [EAX]        //LDR_MODULE鏈表頭的Flink指標
            LEA EBX,DWORD PTR [EAX+1CH]    //獲取_LDR_DATA_TABLE_ENTRY結構中的成員BaseDllName指標
            MOV CX,WORD PTR [EBX]         //獲取BaseDllName->Length
            MOV EDI,DWORD PTR [EBX+4H]    //獲取BaseDllName->buffer
            
            CMP ECX,0
            JE  _LOOP
            CMP CX, 24
            JNE  _LOOP
        
            PUSH EAX                     //保存LDR_MODULE鏈表指標
//...................................................................................................            
            push  ECX                   //strcmpwi函數的三個參數
            push  ESI
            push  EDI                            
//...................................................................................................  
            push    0                    //填充返回偽值
            push    ebp
            mov     ebp, esp
            sub     esp, 48h
            push    ebx
            push    esi
            push    edi
            lea     edi, [ebp-48H]
            mov     ecx, 12h
            mov     eax, 0CCCCCCCCh
            rep stosd
            mov     [ebp-4], 0
            jmp     short loc_40104A


loc_401041:
            mov     eax, [ebp-4]
            add     eax, 1
            mov     [ebp-4], eax

loc_40104A:
            mov     ecx, [ebp-4]
            cmp     ecx, [ebp+10H]
            jnb     short loc_40109D
            mov     edx, [ebp+8H]
            add     edx, [ebp-4]
            xor     eax, eax
            mov     al, [edx]
            cmp     eax, 41h
            jl      short loc_401080
            mov     ecx, [ebp+8]
            add     ecx, [ebp-4]
            xor     edx, edx
            mov     dl, [ecx]
            cmp     edx, 5Ah
            jg      short loc_401080
            mov     eax, [ebp+8]
            add     eax, [ebp-4]
            xor     ecx, ecx
            mov     cl, [eax]
            add     ecx, 20h
            mov     byte ptr [ebp-8], cl

loc_401080:
            mov     edx, [ebp-8]
            and     edx, 0FFh
            mov     eax, [ebp+0ch]
            add     eax, [ebp-4]
            xor     ecx, ecx
            mov     cl, [eax]
            cmp     edx, ecx
            jz      short loc_40109B
            xor     eax, eax
            jmp     short loc_4010A2


loc_40109B:
            jmp     short loc_401041


loc_40109D:
            mov     eax, 1

loc_4010A2:
            pop     edi
            pop     esi
            pop     ebx
            mov     esp, ebp
            pop     ebp
            add     esp,16                  //平衡堆疊
//...................................................................................................                
            CMP EAX,0
            JNE  _FINDED
            POP EAX
            JMP  _LOOP
                                                       
_FINDED:
            POP  EAX
            MOV EAX, DWORD PTR[EAX + 8]   //獲取kernel32.dll的基底位址
            ADD ESP, 24


2011年9月12日 星期一

[動畫教學] 程式碼快速簡轉繁

今天來做個 "程式碼快速簡轉繁"的動畫

雖然是個小技巧,但卻十分好用

進入正題.....

從對岸抓下來的程式碼  都是亂碼

首先呢

1.先把語系修改成Taiwan 然後存檔


2.利用馴碼快手中文化資源 & 程式碼(可以用自己熟悉的中文化工具)

3.翻譯大陸用語

4.Done  OK  這樣就快速轉換完畢囉

By Kost0911  2011.9.12  下次見囉~BYE


動畫地址:http://cn.ziddu.com/download/618502/CodeCnToTw.rar.html


2011年8月14日 星期日

[原創]一個彈出網站的工具分析

慣例的PEiD查下殼,VC6 無殼  成功的第一步


 


首先用OD打開F9執行,我X~程式雖然執行了,但OD卻關閉了


 


破解  


 


從這裡可以知道,載入的只是個Load,而不是真正執行的本體


Ctrl+F2 重新載入, 下 CreateFileA 斷點試試


順利斷下,抓到某個可疑的檔案


破解  


照這目錄手動把檔案抓出來,檔名是tempk.txt
但是! 手動把tempk.txt 副檔名 改成 .exe 就會神奇的發現這是個執行檔


3.bmp  


而且跟Load程式圖標完全一樣,很開心的打開他.....


!?....沒動靜.....再點.....X第二次


看來有某種效驗的樣子,直接就退出了


再重新載入Load,這次用插件搜索字符串


找完後  Ctrl+F 找 tempk 這個可疑的名稱


破解  


應該會出現跟我圖片一樣的地方,雙擊點進去


破解 


現在F8一路往下跟


中途可以跟到一些有趣的東西,像是呼叫DeleteFileA 刪除檔案,


判斷只能有同一行程存在,否則自行結束等等....但現在我直接講關鍵點


F8到下方的地方,看到Winexec這個函數,第2個Push參數,最後面有個tempk.txt cs


這個cs就是重點了,要有這個cs當啟動參數,這個程式才能執行


破解   


OK,接下來重新載入tempk.txt 填入啟動參數cs


破解  


F9執行~登登  果然成功執行了


但這樣挺麻煩的,所以還是要找關鍵點改掉他才方便


先去掉啟動參數  故意讓他結束程式


下ExitProcess斷點 ,再使用堆疊回朔向上找


最後有個關鍵位置


破解  


把je 改 jmp 就可以不讓程式中斷了~打了一堆 終於要進入Crack的部分了


破解  


點開註冊按鈕,出現這個視窗,點"註冊" 亂輸入註冊碼後,會發現程式又直接結束了


看起來似乎是重啟驗證型的


重新載入後這裡直接斷bpx RegOpenKeyExA


一個Retn 10返回後,會看到一些關鍵的東西~破解  


這裡在讀取註冊表,繼續F8往下會發現一個關鍵地方


破解  


這裡就是關鍵點了,406711的跳轉如果跳了,就註冊失敗


可能一些朋友看到這就忍不住想把jnz Nop掉吧~


但這樣改後,雖然看起來像破解成功了,但是對exe加網站後,註冊提示馬上又跑出來了


其實關鍵在[ebp+60]這裡,這個記憶體位置會多次效驗是不是1


所以只要把 cmp byte ptr ss:[ebp+60],1  改成


                mov byte ptr ss:[ebp+60],1


這樣就可以完全破解了


其實如果丟到虛擬機的話,還有個效驗,不過也是斷MessageBoxA就可以清除了


至於中文化甚麼的就非常簡單了~就不贅述了


 


PS:從這程式裡學到了,躲貓貓式的隱藏檔案


    啟動參數的效驗 & 全域變量的修改


    還有個虛擬機的檢測


雖然是個小東西,但還是挺有意思的。


 


想要玩玩這個軟體的可以到這裡抓:


http://cn.ziddu.com/download/613392/InsertWeb.rar.html


By   Kost0911 2011.8.15