老文章档案 · 2003 年

利用DebugAPI做一些原先手工完成的动作

破解教程 · 补丁技术 · 2003-06-22 · 作者:bag001 人气: · 出处:嬴政天下整理收藏)

利用DebugAPI做一些原先手工完成的动作,我用这种方法做过内存补丁,内存注册机等,完全VC

内容:

这段代码针对的是LanTalk XP v2.7.1.0 Build 7123

// LanTalk_ldr.cpp : Defines the entry point for the application.

//

#include "stdafx.h"

#include <stdlib.h>

#include "shlwapi.h"

#pragma comment(lib, "shlwapi.lib")

typedef struct

{

LPVOID lpAddr;

BYTE byData;

DWORD nCount;

} BPDATA;

BPDATA g_bpData[10] = {0};

BOOL SetBreakPoint(HANDLE hProcess, LPVOID lpAddr, UINT nNum)

{

if (nNum >= sizeof(g_bpData) / sizeof(BPDATA)) return FALSE;

BYTE byTemp;

DWORD dwNewProt, dwOldProt;

VirtualProtectEx(hProcess, lpAddr, 1, PAGE_EXECUTE_READWRITE, &dwOldProt);

BOOL bOK = ReadProcessMemory(hProcess, lpAddr, &byTemp, 1, NULL);

if (!bOK) goto End;

g_bpData[nNum].lpAddr = lpAddr;

g_bpData[nNum].byData = byTemp;

g_bpData[nNum].nCount = 0;

byTemp = 0xcc;

bOK = WriteProcessMemory(hProcess, lpAddr, &byTemp, 1, NULL);

End:

VirtualProtectEx(hProcess, lpAddr, 1, dwOldProt, &dwNewProt);

return bOK;

}

BOOL RemoveBreakPoint(HANDLE hProcess, UINT nNum)

{

if (nNum >= sizeof(g_bpData) / sizeof(BPDATA)) return FALSE;

BYTE byTemp;

DWORD dwNewProt, dwOldProt;

LPVOID lpAddr = g_bpData[nNum].lpAddr;

VirtualProtectEx(hProcess, lpAddr, 1, PAGE_EXECUTE_READWRITE, &dwOldProt);

BOOL bOK = ReadProcessMemory(hProcess, lpAddr, &byTemp, 1, NULL);

bOK = (byTemp == 0xcc);

if (!bOK) goto End;

bOK = WriteProcessMemory(hProcess, lpAddr, &g_bpData[nNum].byData, 1, NULL);

if (bOK) ZeroMemory(g_bpData + nNum, sizeof(BPDATA));

End:

VirtualProtectEx(hProcess, lpAddr, 1, dwOldProt, &dwNewProt);

return bOK;

}

BOOL GetDllName(HANDLE hProcess, LPLOAD_DLL_DEBUG_INFO lddi, LPSTR dll_name, int nSize)

{

LPVOID ptr = 0;

ReadProcessMemory(hProcess, lddi->lpImageName, &ptr, sizeof(ptr), NULL);

if( ptr == 0 ) return FALSE;

WCHAR dll_name_u[MAX_PATH + 1] = {0};

ReadProcessMemory(hProcess, ptr, dll_name_u, sizeof(dll_name_u), NULL);

if( dll_name_u[0] == 0 ) return FALSE;

if( lddi->fUnicode )

wcstombs(dll_name, dll_name_u, nSize);

else

lstrcpyn(dll_name, (LPSTR)dll_name_u, nSize);

return TRUE;

}

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

STARTUPINFO si = {0};

PROCESS_INFORMATION pi = {0};

// Start the child process.

if( !CreateProcess( NULL, // No module name (use command line).

//"D:\\Program Files\\Lantalk XP\\LanTalk.exe", // Command line.

"LanTalk.exe", // Command line.

NULL, // Process handle not inheritable.

NULL, // Thread handle not inheritable.

TRUE, // Set handle inheritance to FALSE.

DEBUG_ONLY_THIS_PROCESS, // creation flags.

NULL, // Use parent's environment block.

//"D:\\Program Files\\Lantalk XP\\",

NULL, // Use parent's starting directory.

&si, // Pointer to STARTUPINFO structure.

&pi ) // Pointer to PROCESS_INFORMATION structure.

)

{

MessageBox(NULL, "CreateProcess failed.", "Error", MB_OK);

return 0;

}

LPVOID lpBase[] = {

0, // kernel32.GetVersion

0, // kernel32.GetCommandLineA

LPBYTE(0x0099f8c0), // get clsid string

0, // advapi32.RegCreateKeyExA

LPBYTE(0x00402255), // jnz xxx (75 15) --- change to jmp xxx (eb 15)

};

// 设置前两个断点的目的是为了跳过ASProtect 1.2x的解密过程,

// 第三个断点获得注册表键值

// 最后一个断点作了一个内存补丁

HMODULE hModule = LoadLibrary("kernel32.dll");

lpBase[0] = GetProcAddress(hModule, "GetVersion");

lpBase[1] = GetProcAddress(hModule, "GetCommandLineA");

FreeLibrary(hModule);

hModule = LoadLibrary("advapi32.dll");

lpBase[3] = GetProcAddress(hModule, "RegCreateKeyExA");

FreeLibrary(hModule);

DEBUG_EVENT dbg = {0};

CONTEXT context = {0};

while (WaitForDebugEvent(&dbg, INFINITE))

{

if (dbg.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)

{

char dll_name[MAX_PATH] = {0};

if (GetDllName(pi.hProcess, &dbg.u.LoadDll, dll_name, sizeof(dll_name)))

{

if (*dll_name)

{

char *p = strrchr(dll_name, '\\');

if (p && lstrcmpi(p + 1, "kernel32.dll") == 0)

SetBreakPoint(pi.hProcess, lpBase[0], 0);

}

}

}

else if (dbg.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)

{

if (dbg.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)

{

LPVOID lpAddr = dbg.u.Exception.ExceptionRecord.ExceptionAddress;

if (lpAddr == lpBase[0] || lpAddr == lpBase[1])

{

context.ContextFlags = CONTEXT_CONTROL;

if (GetThreadContext(pi.hThread, &context))

{

RemoveBreakPoint(pi.hProcess, 0);

context.Eip--;

SetThreadContext(pi.hThread, &context);

if (lpAddr == lpBase[0])

SetBreakPoint(pi.hProcess, lpBase[1], 0);

else

SetBreakPoint(pi.hProcess, lpBase[2], 1);

}

}

else if (lpAddr == lpBase[2])

{

context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;

if (GetThreadContext(pi.hThread, &context))

{

RemoveBreakPoint(pi.hProcess, 1);

context.Eip--;

SetThreadContext(pi.hThread, &context);

LPVOID ptr = NULL;

if (ReadProcessMemory(pi.hProcess, (LPVOID)context.Ebx, &ptr, sizeof(ptr), NULL))

{

char szClsid[45] = {0};

if (ReadProcessMemory(pi.hProcess, ptr, szClsid, sizeof(szClsid), NULL))

SHDeleteKey(HKEY_CLASSES_ROOT, szClsid);

}

SetBreakPoint(pi.hProcess, lpBase[3], 0);

}

}

else if (lpAddr == lpBase[3])

{

context.ContextFlags = CONTEXT_CONTROL;

if (GetThreadContext(pi.hThread, &context))

{

RemoveBreakPoint(pi.hProcess, 0);

context.Eip--;

SetThreadContext(pi.hThread, &context);

DWORD dwTemp = 0;

ReadProcessMemory(pi.hProcess, lpBase[4], &dwTemp, 4, NULL);

if (dwTemp == 0xbe391575)

{

dwTemp = 0xeb;

WriteProcessMemory(pi.hProcess, lpBase[4], &dwTemp, 1, NULL);

}

}

}

ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);

}

}

else if (dbg.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)

break;

ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);

}

CloseHandle(pi.hProcess);

CloseHandle(pi.hThread);

return 0;

}

标 题:再贴一个使用类似方法的内存注册机, (5千字)

发信人:bag001

时 间:2002-12-27 15:56:57

详细信息:

一年多以前写的,针对版本有些老(好像是2.4-3.0),新版的算法分析论坛里有,只作方法演示用,代码中使用了特征代码查询方式,以适应版本更新,只要算法不变,可以用在不同版本上。

该软件在计算注册码时分为两部分,前一部分比较简单,后一部分很复杂,但只要使用后一部分算出来的结果根据前一部分的计算逻辑,很容易就可以算出注册码。

// cr-cglc.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

unsigned int decode(unsigned int num);

LPBYTE search(LPBYTE pbuff, int oSize, LPBYTE sub, int subSize)

{

for (int i = 0; i < oSize - subSize; i++, pbuff++)

{

if (*pbuff == *sub)

{

if (memcmp(pbuff, sub, subSize) == 0)

return pbuff;

}

}

return NULL;

}

#define BUFF_SIZE 1024 * 1024

int main(int argc, char* argv[])

{

STARTUPINFO si = {0};

PROCESS_INFORMATION pi = {0};

// Start the child process.

if( !CreateProcess( NULL, // No module name (use command line).

"mygp.exe", // Command line.

NULL, // Process handle not inheritable.

NULL, // Thread handle not inheritable.

FALSE, // Set handle inheritance to FALSE.

0, // No creation flags.

NULL, // Use parent's environment block.

NULL, // Use parent's starting directory.

&si, // Pointer to STARTUPINFO structure.

&pi ) // Pointer to PROCESS_INFORMATION structure.

)

{

printf( "CreateProcess failed." );

return 0;

}

WaitForInputIdle(pi.hProcess, INFINITE);

// 定义特征代码

unsigned char orig1[] = {0x8b, 0xc6, 0x01, 0x55, 0x88};

unsigned char orig2[] = {0x29, 0x45, 0x88, 0x8d, 0x45, 0xfc};

unsigned char orig3[] = {0x29, 0x45, 0x88, 0x83, 0x7d, 0x88, 0x00};

unsigned char buff1[5], buff2[6], buff3[7];

DWORD bytes;

LPBYTE lpbase = LPBYTE(0x401000);

LPBYTE pbuff = new BYTE[BUFF_SIZE];

// 读取待扫描区域,这里只使用了简单的读定长数据,

BOOL bok = ReadProcessMemory(pi.hProcess,

lpbase, pbuff, BUFF_SIZE, &bytes);

if (!bok)

{

delete pbuff;

return 0;

}

// 扫描特征码

lpbase = search(pbuff, BUFF_SIZE, orig1, sizeof(orig1));

// 判断找到的位置是否正确

if (lpbase == NULL ||

memcmp(lpbase + 10, orig2, sizeof(orig2)) != 0 ||

memcmp(lpbase + 21, orig3, sizeof(orig3)) != 0)

{

delete pbuff;

printf("regcode not found.");

TerminateProcess(pi.hProcess, -1);

CloseHandle( pi.hProcess );

CloseHandle( pi.hThread );

return 0;

}

lpbase = (LPBYTE)0x401000 + (lpbase - pbuff);

LPBYTE lpbase1 = lpbase;

LPBYTE lpbase2 = lpbase + 10;

LPBYTE lpbase3 = lpbase + 21;

delete pbuff;

bok = ReadProcessMemory(pi.hProcess,

lpbase1, buff1, sizeof(buff1), &bytes);

if (memcmp(buff1, orig1, sizeof(buff1)) == 0)

{

buff1[0] = 0xcc;

WriteProcessMemory(pi.hProcess,

lpbase1, buff1, sizeof(buff1), &bytes);

}

bok = ReadProcessMemory(pi.hProcess,

lpbase2, buff2, sizeof(buff2), &bytes);

// 设置断点1

if (memcmp(buff2, orig2, sizeof(buff2)) == 0)

{

buff2[0] = 0xcc;

WriteProcessMemory(pi.hProcess,

lpbase2, buff2, sizeof(buff2), &bytes);

}

bok = ReadProcessMemory(pi.hProcess,

lpbase3, buff3, sizeof(buff3), &bytes);

// 设置断点2

if (memcmp(buff3, orig3, sizeof(buff3)) == 0)

{

buff3[0] = 0xcc;

WriteProcessMemory(pi.hProcess,

lpbase3, buff3, sizeof(buff3), &bytes);

}

// 进入调试状态

bok = DebugActiveProcess(pi.dwProcessId);

DEBUG_EVENT dbg = {0};

unsigned int x, y, z;

CONTEXT context = {0};

while (WaitForDebugEvent(&dbg, INFINITE))

{

if (dbg.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)

{

if (dbg.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)

{

if (dbg.u.Exception.ExceptionRecord.ExceptionAddress == lpbase1)

{

context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;

if (GetThreadContext(pi.hThread, &context))

{

context.Eip--;

WriteProcessMemory(pi.hProcess,

lpbase1, orig1, sizeof(orig1), &bytes);

SetThreadContext(pi.hThread, &context);

bok = ReadProcessMemory(pi.hProcess,

LPVOID(context.Ebp - 0x78), &x, sizeof(x), &bytes);

}

}

else if (dbg.u.Exception.ExceptionRecord.ExceptionAddress == lpbase2)

{

context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;

if (GetThreadContext(pi.hThread, &context))

{

context.Eip--;

WriteProcessMemory(pi.hProcess,

lpbase2, orig2, sizeof(orig2), &bytes);

SetThreadContext(pi.hThread, &context);

y = context.Eax;

}

}

else if (dbg.u.Exception.ExceptionRecord.ExceptionAddress == lpbase3)

{

context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;

if (GetThreadContext(pi.hThread, &context))

{

context.Eip--;

WriteProcessMemory(pi.hProcess,

lpbase3, orig3, sizeof(orig3), &bytes);

SetThreadContext(pi.hThread, &context);

z = context.Eax;

printf("Your Register Code is:\n");

// 计算注册码

printf("%08X\n", decode(y + z - x));

}

}

}

}

else if (dbg.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)

break;

bok = ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE);

}

CloseHandle(pi.hProcess);

CloseHandle(pi.hThread);

return 0;

}

unsigned int decode(unsigned int num)

{

_asm {

mov ebx, 3

mov ecx, num

xor ecx, 0x81079516

start:

mov dh, cl

mov dl, ch

shl dx, 7

mov al, dh

ror eax, 8

ror ecx, 8

mov dh, cl

mov dl, ch

shl dx, 7

mov al, dh

shr ecx, 8

mov dh, cl

mov dl, ch

shl dx, 7

mov ah, dh

ror eax, 16

shr ecx, 8

mov dh, cl

mov dl, ch

shl dx, 7

mov al, dh

dec ebx

jz end

mov ecx, eax

jmp start

end:

}

}

标 题:关于自调试的几点想法 (1千字)

发信人:bag001

时 间:2002-12-27 23:26:12

详细信息:

据我所知,通常DebugApi只要在两个进程之间就能产生作用,而不管是否在同一个执行档中。

如果你所说的自调试仅仅是指在同一个执行档中进行自我调试的话,Armadillo的加密方法可以说是一个很好的例子。正由于它的自调试方式,使得使用它进行加密的程序天生就具有Anti-Debug能力。

如果是要求在同一个进程中进行自调试,那我们就不能这么做(我从不知道在调用DebugActiveProcess时将当前进程的ID传给它的结果是什么)。

其实调试的过程我们可以看做是程序在某个特定点产生某个事件,由调试器捕捉到该事件进行相应的处理,然后回到断点处继续执行的过程,这一点跟SEH中的EXCEPTION_CONTINUE_EXECUTION方式有些类似,基于这一点考虑,我想是否能够在希望程序产生断点的位置人为的产生某种异常(如div0之类的),让我们事先安装好的异常处理程序来接管控制权进行处理,处理完毕后再返回断点处继续处理。

另外一个想法断点其实就是一个特殊的中断(INT3),我们可以安装一个中断处理程序,在希望断点处发生一个中断,接下来的处理就跟原先的处理差不多了。 (出处:嬴政天下整理收藏)

相关文章:

·WinRip 2.0保护机制分析及其补丁制作

·注册机和补丁制作之一概念介绍

·注册机和补丁制作之二文件补丁制作

·注册机和补丁制作之三内存补丁制作

·用SMC的补丁方法来破解加壳的幻影2003

·侠盗猎车免cd补丁

·邹丹补丁教学

·破解ASPack 2.000 及其补丁制作教学

相关软件:

·贤内助 2.00破解补丁

·英语词汇逻辑记忆法1.0 破解补丁

·度量衡 v1.0 破解补丁

·金蝶决策支持系统2.0解狗补丁

·速达2000+pro 时间功能限制去除补丁

·速达3000服装版正式版3.2补丁

·瑞星2001(12.22版本,5月10日)免安装盘补丁

·中文之星智能狂拼Ⅱ补丁程序驱除限制文件

·东方影都去掉60天限制补丁

·家庭电脑像册制作系统v4.0补丁

→ 特别推荐

→ 热点TOP10

我为人人《《==》》人人为我

关于我们 |

帮助(?)

| 广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright © 1999-2003

winzheng.com All Rights Reserved.

繁体版:由华琦数码技术提供

Powered

by:MeSky.Net

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史