首先声明一下,虽然写的原创,但源代码里面还是有一些是网上复制来的,如有雷同,纯属共享.
在看雪注册好多年了....还是个临时会员....多年的挂机后今年我算发现了,几年才涨了
伍点Kx,估计再挂四五年也买不起注册码....
好吧,终于被我发现原来发个优秀的帖子就能成会员.看来只有发贴试试了.
最近在研究DLL注入,就发一篇相关的文档吧...
本帖子的特色就是,惰性注入.为什么叫惰性呢,就是咱们不主动去注.只对程序简单的内存读写(当初以为只读写,360就不会报毒了,结果很失望,一写内存就提示,唉).
与那些什么远程线程注入,修改注册表注入,消息Hook注入,输入法注入,进程启动注入.等我在网上找的注入方式,好像又多了那么一条思路,哈哈.
先说下注入的思路:
在程序必定会执行的某个代码段里面写入一个跳转指令.
跳到咱们用机器码写的加载DLL的代码里面.
然后加载完后跳回去,哈哈不就注入了吗.
惰性这个词就是因为这个来的,因为要等程序自己来执行那个被咱们写入跳转指令的代码段里面来时,咱们的DLL,才会被加载.
思路是这样的,接下来咱们就开始设计咱们的代码吧.
要读写非本身程序的内存我似乎只会简单的
取得窗口句柄-->取得进程句柄-->打开进程并取得操作ID-->然后就用这个操作ID读写内存了.
HWND hwnd = FindWindowA("XLong", "isgoodtime");
\/
\/
DWORD ProcessId;GetWindowThreadProcessId(hwnd,&ProcessId);
\/
\/
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, ProcessId);
\/
\/
BYTE szBuff[5];ReadProcessMemory(hProcess, baseAddress, szBuff, 5, 0);WriteProcessMemory(hProcess,(LPVOID)((long)menoryAddess + 256), exePath, sizeof(exePath), 0);
以上就是读写内存的相关流程及WIN32API.
好,现在咱们能读写咱们要注入的程序里面的内容了.那咱们就先去要注入的程序里面找一个必定会执行的代码片段,再把咱们的跳转命令用写入内存的方式写入到某一行里面(我的例子里面是写在一个按钮事件里面,当咱们惰性注入后,一点这个按钮咱们的DLL就注入了).
好要跳了,但咱们跳到哪里去呢.这就得去目标进程里面去分配一段内存(或利用目标程序的空闲内存也行),分完段内存后,咱们就要往里面写入咱们的加载DLL的相关机器码了.会用到的相关WIN32API我都列出来.
LPVOID menoryAddess = VirtualAllocEx(hProcess,0,512,MEM_COMMIT ,PAGE_READWRITE);//分配一块内存放代码
\/
\/
WriteProcessMemory(hProcess, menoryAddess , szCodeBuff, sizeof(szCodeBuff), 0);//将传入的代码 写入分配的内存中
经过以上的分配内存,写入机器码后,那么当程序点按钮时咱们的DLL就会被回载了.
以上关于咱们的注入程序的流程是走完了.但费了我相当多的脑力的还是那段机器码要怎么写.由于 我对汇编不太熟悉,真是绞尽了脑汁才写好.
下面我也介绍一下机器的流程吧.随带列出一下要用到的WIN32API.
机器码流程:
当程序跳到咱们的代码时. 由于咱们的惰性,所以不知道程序到底什么时候会跳进来,所以咱们要在这段代码里来恢复之前咱们的"注入程序"里面修改成跳转的代码.(所以上面所写的程序流程里还缺了一步就是把要改的那个地方的代码先保存5字节.)
然后要能修改程序的内存,居然还要修改内存的保护属性....(我查了许多资料才解决掉这个错误,许多资料介绍了用WriteProcessMemory可以写,而自己简单的mov却会报错,原来是WriteProcessMemory这个函数会自动判断是否能写,不能的会改成可写,写完后又把不可写改回来)
好现在咱们把原来的五字节代码恢复了,剩下来就得加载咱们的DLL了.
再不加载就完完了,因为跳转的代码刚刚被咱们恢复了,不会再来执行咱们这段代码了,哈哈.
加载DLL的流程比较简单(只是从简了,真要写没这么简单,呵呵.),首先把咱们的DLL路径压栈,再一调用系统的LoadLibraryA()函数,咱们的DLL就加载进来啦,哈哈.
加载完咱们就跳回程序原来的代码中去,让他去做自己的事咯(感觉咱们应该清理这段由咱们分配的内存,不过我不会...).
思路和流程都介绍完了.下面咱就根据这思路去看看我写的一段示例代码吧,哈哈.不过提前说下,咱们那卸载DLL的代码我没完成.抱歉抱歉,嘿嘿.
BOOL PostDataToProcess(HWND hwnd ,LPVOID baseAddress,char * DLLname,BOOL InOrFree)
{
SeDebugPrivilege();
DWORD ProcessId;
GetWindowThreadProcessId(hwnd,&ProcessId);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, ProcessId);
BYTE szBuff[5];
ReadProcessMemory(hProcess, baseAddress, szBuff, 5, 0);//读取原地址的五个字节保存下来
LPVOID menoryAddess = VirtualAllocEx(hProcess,0,512,MEM_COMMIT ,PAGE_READWRITE);//分配一块内存放代码
if(InOrFree)//如果为注入
{
char exePath[256];
GetModuleFileNameA(NULL, exePath, 256);//取得程序的绝对路径
for(int i = sizeof(exePath);i>=0;i--)//拼接DLL路径
{
if(exePath[i] == '\\')
{
for(int j = i+1;j<getlen(DLLname)+i+1;j++)
{
exePath[j] = DLLname[j - i - 1];
}
exePath[getlen(DLLname)+i+1] = '\0';
break;
}
}
WriteProcessMemory(hProcess,(LPVOID)((long)menoryAddess + 256), exePath, sizeof(exePath), 0);//将DLL路径 写入分配的内存中
LPCSTR lpFileName = "kernel32";
HMODULE hModule = GetModuleHandleA(lpFileName);
if(hModule == NULL)
{
hModule = LoadLibraryA(lpFileName);
}
if(hModule != NULL)
{
//FARPROC farproc = GetProcAddress(hModule,"GetModuleHandleA");
//FARPROC farproc = GetProcAddress(hModule,"GetProcAddress");
FARPROC LOADLIBRARYA = GetProcAddress(hModule,"LoadLibraryA");
FARPROC VIRTUALPROTECT = GetProcAddress(hModule,"VirtualProtect");
if(LOADLIBRARYA != 0 && VIRTUALPROTECT != 0)
{
BYTE szCodeBuff[256] = //存放注入DLL的汇机器码
{
0x68,0x00,0x00,0x00,0x00,//PUSH 0 要可以写入的内存,否则将失败❶
0x6A,0x40,//PUSH 40
0x68,0x80,0x00,0x00,0x00,//PUSH 80
0x68,0x00,0x00,0x00,0x00,//PUSH 这里为要修改属性的内存地址❷
//0xFF,0x15,0x00,0x00,0x00,0x00,//CALL VirtualProtect❸
0xBB,0x00,0x00,0x00,0x00,//mov ebx,kernel32.VirtualProtect❸
0xFF,0xD3,//call ebx
0xC6,0x05,0x00,0x00,0x00,0x00,0x00,//mov byte ptr ds:[40102A],0BB❹31
0xC7,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//mov dword ptr ds:[40102B],目标程序.004011C0❺
0x68,0x00,0x00,0x00,0x00,//push 0046C878; /FileName = "user32.dll"❻
//0xFF,0x15,0x00,0x00,0x00,0x00,//call dword ptr ds:[<&KERNEL32.LoadLibrar>; LoadLibraryA❼
0xBB,0x00,0x00,0x00,0x00,//mov ebx,kernel32.VirtualProtect❼
0xFF,0xD3,//call ebx
0xE9,0x00,0x00,0x00,0x00 //jmp dword ptr ds:[46669C]; 目标程序.00417160❽
};
PushAddressToBYTE(szCodeBuff,(LPVOID)((long)menoryAddess + 256 + strlen(exePath) + 1),1);//❶
PushAddressToBYTE(szCodeBuff,baseAddress,13);//❷
PushAddressToBYTE(szCodeBuff,(LPVOID)VIRTUALPROTECT,18);//❸
PushAddressToBYTE(szCodeBuff,baseAddress,26);//❹
szCodeBuff[30] = szBuff[0];//❹
PushAddressToBYTE(szCodeBuff,(LPVOID)((long)baseAddress+1),33);//❺
PushAddressToBYTE(szCodeBuff,szBuff,37);//❺-----
PushAddressToBYTE(szCodeBuff,(LPVOID)((long)menoryAddess + 256),42);//❻DLL 路径
PushAddressToBYTE(szCodeBuff,(LPVOID)LOADLIBRARYA,47);//❼//LoadLibraryA 函数地址
INT32 jmptoaddress = (long)baseAddress - (long)menoryAddess - 58;//计算回跳地址
PushAddressToBYTE(szCodeBuff,(LPVOID)jmptoaddress,54);//❽些值为计算所得
WriteProcessMemory(hProcess, menoryAddess , szCodeBuff, sizeof(szCodeBuff), 0);//将传入的代码 写入分配的内存中
}
}
else
{
return false;
}
}
else
{
LPCSTR lpFileName = "kernel32";
HMODULE hModule = LoadLibraryA(lpFileName);
FARPROC farproc = GetProcAddress(hModule,"FreeLibrary");
BYTE szCodeBuff[256];//存放卸载DLL的代码
WriteProcessMemory(hProcess, menoryAddess , szCodeBuff, sizeof(szCodeBuff), 0);//将传入的代码 写入分配的内存中
}
BYTE JmpCod[] = {0xE9,0x00,0x00,0x00,0x00};
INT32 jmptoaddress = (long)menoryAddess - 5 - (long)baseAddress;//计算跳转地址
PushAddressToBYTE(JmpCod,(LPVOID)jmptoaddress,1);//填充跳转地址
WriteProcessMemory(hProcess, baseAddress , JmpCod, 5, 0);//修改相关地址跳到传入的代码处开始执行
return true;
}
整个示例打包上传了,详情看附件
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)