第一次有耐心脱壳,脱完后,才在这里知道是 CrypKeyInstant,我脱的版本到底是多少这就不太清楚 ,但是和很下面这个链接上的讨论很像:双进程,大量 cc,抽代码。
http://bbs.pediy.com/showthread.php?t=33856
这个壳代码很清晰,并且抽出代码没有加密,所以搞起来也比较容易,没有多少技术含量,高手可以略过。
/////////////////////////////////////////////////////////////////////////////////////////////////////
// 写的很乱, 写的时候很有针对性。
// 如果要要改, 把 protected_module_table 改为发生异常后第一个循环查找的 call 的返回值
//
#include <windows.h>
#include <stdio.h>
//char* protected_module_table = (char*)0x4034B0;
//
typedef unsigned long u32;
#include <PSHPACK1.H>
struct trap_record
{
char attr; //
u32 trap_addr;
u32 patch_code_record_off;
u32 patch_code_record_size;
};
#include <poppack.h>
// struct patch_code_record
// {
// char is_used;
// // char patch_code[1];
// };
//base --> 0x20
//first --> 0x48aea
HANDLE __hProcess1, __hProcess2;
u32 __trap_hash_table;
void* __big_buf = NULL;
void __fastcall xf(u32 p_tr)
{
trap_record tr;
u32 tmp;
if (
!ReadProcessMemory(__hProcess1, (void*)p_tr, &tr, sizeof (tr), &tmp)
)
{
printf("读取地址 %08X 失败!\n", p_tr);
return ;
}
if ( tr.attr == 0 )
{
xf(tr.patch_code_record_off + __trap_hash_table);
xf(tr.patch_code_record_size + __trap_hash_table);
}
else
{
printf(
"trap_record.attr = 0x%08X\n"
"trap_record.trap_addr = 0x%08X\n"
"trap_record.patch_code_record_off = 0x%08X\n"
"trap_record.patch_code_record_size = 0x%08X\n"
"-------------------------------------------------------\n",
tr.attr,
tr.trap_addr,
tr.patch_code_record_off,
tr.patch_code_record_size
);
ReadProcessMemory(__hProcess1, (PVOID)(__trap_hash_table + tr.patch_code_record_off + 1), __big_buf, tr.patch_code_record_size, &tmp);
WriteProcessMemory(__hProcess2, (PVOID)tr.trap_addr, __big_buf, tr.patch_code_record_size, &tmp);
FlushInstructionCache(__hProcess2, (PVOID)tr.trap_addr, tr.patch_code_record_size);
}
}
int main(int argc, char* argv[])
{
DWORD dwPid1, dwPid2;
printf("请分别输入调试和被调试进程的 PID: \n");
scanf("%d %d", &dwPid1, &dwPid2);
// BOOL bOK = DebugActiveProcess(dwPid1); // 暂停调试器
// if ( !bOK )
// {
// printf("绑定 %d 进程失败!\n", dwPid1);
// return -1;
// }
//
// DEBUG_EVENT de;
// if ( !WaitForDebugEvent(&de, 5000) )
// {
// printf("等待 %d 进程的调试事件失败!\n");
// return -2;
// }
//
// HANDLE hProcess1 = de.u.CreateProcessInfo.hProcess;
// 最好在打开这两个进程的之前已经暂停
HANDLE hProcess1 = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION, FALSE, dwPid1);
HANDLE hProcess2 = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid2);
__hProcess1 = hProcess1;
__hProcess2 = hProcess2;
if ( hProcess2 == NULL || hProcess1 == NULL )
{
printf("打开 %d 进程进行写操作失败!\n");
return -3;
}
u32 *index_table = NULL;
__try
{
u32 tmp;
u32 a[3];
ReadProcessMemory(hProcess1, (PVOID)0x4034B0, a + 0, 4, &tmp);
ReadProcessMemory(hProcess1, (PVOID)(a[0] + 0x18), a + 1, 4, &tmp);
ReadProcessMemory(hProcess1, (PVOID)(a[0] + 0x38), a + 2, 4, &tmp);
__big_buf = VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT, PAGE_READWRITE);
__trap_hash_table = a[2];
xf(a[1] + a[2]);
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
printf("发生了一个异常!\n");
}
if ( __big_buf != NULL )
{
VirtualFree(__big_buf, 1024 * 1024, MEM_DECOMMIT);
VirtualFree(__big_buf, 0, MEM_RELEASE);
__big_buf = NULL;
}
printf("ok Dump!!\n");
scanf("%d", &dwPid1);
return 0;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课