动态链接库基础与远程线程注入
目录
动态链接库的基本调用
#include<stdio.h>
#include<Windows.h>
#include<Psapi.h>
//有头文件的话可以直接调用头文件
//没有的话就用函数指针
typedef int (*fnrkadd)(int numberA, int numberB);
int main()
{
//这个函数是有操作系统提供给我们的SDK
//SDK软件开发工具包
//API 开放的函数接口 windows给我们写好的代码
//动态链接库里提供的
//系统调用
//开发过程中dll放在代码目录下 编好的话放在exe目录下
MessageBoxA(NULL,"Msg","Msg",MB_OK);
HMODULE hDll = LoadLibraryA("Dll2.dll");//(显示)加载动态链接库 返回动态链接库的句柄也可以说是动态链接库的加载基址
//参数是动态链接库的名字或者说路径
fnrkadd func = (fnrkadd)GetProcAddress(hDll,"rkadd");//返回值返回函数类型
int nRes = func(1, 2);
printf("%d\r\n",nRes);
system("pause");
return 0;
}
MessageBox不直接调用
#include<stdio.h>
#include<Windows.h>
#include<Psapi.h>
//有头文件的话可以直接调用头文件
//没有的话就用函数指针
typedef int (*fnrkadd)(int numberA, int numberB);
typedef int(WINAPI *FnMessageBoxA)(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);
int main()
{
//这个函数是有操作系统提供给我们的SDK
//SDK软件开发工具包
//API 开放的函数接口 windows给我们写好的代码
//动态链接库里提供的
//系统调用
//开发过程中dll放在代码目录下 编好的话放在exe目录下
/*MessageBoxA(NULL, "Msg", "Msg", MB_OK);
HMODULE hDll = LoadLibraryA("Dll2.dll");//(显示)加载动态链接库 返回动态链接库的句柄也可以说是动态链接库的加载基址
//参数是动态链接库的名字或者说路径
fnrkadd func = (fnrkadd)GetProcAddress(hDll,"rkadd");//返回值返回函数类型
int nRes = func(1, 2);
printf("%d\r\n",nRes);*/
HMODULE hUser32 = LoadLibraryA("user32.dll");
FnMessageBoxA Msg= (FnMessageBoxA)GetProcAddress(hUser32, "MessageBoxA");
Msg(NULL,"Msg","Msg",MB_OK);
printf("Msg:%X\r\n",Msg);
printf("MessageBoxA:%X\r\n", MessageBoxA);
system("pause");
return 0;
}
远程线程注入
#include<stdio.h>
#include<Windows.h>
/*
typedef DWORD ThreadCallBack(
LPVOID lpThreadParameter
);
//------------------------------------两者几乎一样 几乎是可以通用的
//-----------------------------------完全可以把LoadLibrary当成CreateThread的回调函数来使用
//四字节的整数(x86)
HMODULE
WINAPI
LoadLibraryW(
_In_ LPCWSTR lpLibFileName
);
*/
BOOL Inject(DWORD dwProcessID, const WCHAR* szPath)//进程ID 路径
{
//LoadLibrary
//CreateRemoteThread
//1.打开目标进程获取句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID);
//2.在目标进程体内申请空间
//VirtualAlloc() 在本进程中申请空间 Ex是在目标进程内申请空间 区别为第一个参数是否为进程句柄
LPVOID lpAddress = VirtualAllocEx(hProcess,NULL,0x100,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);//不指定地址随机分配
//函数返回一个地址空间(一个指针)
//3.写入DLL路径
SIZE_T sWriteLength = 0;
BOOL bRet = WriteProcessMemory(hProcess, lpAddress, szPath,((wcslen(szPath)+1)*2),&sWriteLength);
if (bRet == FALSE)
{
MessageBoxA(NULL, "WriteProcessMemory Failed!", "Error", MB_OK);
return FALSE;
}
/*把路径写入目标体内再调用远程线程创建的时候调用LoadLibrary就可以在目标体内的内存内找到字符串了
写到自己的空间内是没有用的 因为有一个内存隔离不能互相搞 所以需要写到目标的体内*/
//4.创建远程线程,执行LoadLibrary回调
HANDLE hThread = CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddress,NULL,NULL);
//5.等待远程线程执行结束(LoadLibrary返回了)
WaitForSingleObject(hThread,INFINITE);
//6.释放空间
VirtualFreeEx(hProcess,lpAddress,0,MEM_RELEASE);
//7.释放句柄
CloseHandle(hProcess);
CloseHandle(hThread);
//8.返回结果
return TRUE;
}
int main()
{
Inject(10648, L"C:\\Users\\wakappxc\\Desktop\\Dll2.dll");
system("pause");
return 0;
}
DLL写法
dllmain.cpp
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
//DllMain 动态链接库的入口
//真正的API的东西不是在这里面处理的而是一种导出函数的东西
//PE文件(windows可执行文件的一个格式 exe dll sys)
//PE文件中的导出表
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH://附加到进程的时候
MessageBox(NULL,L"Msg",L"Msg",MB_OK);
break;
case DLL_THREAD_ATTACH://附加到线程的时候
break;
case DLL_THREAD_DETACH://线程剥离的时候
break;
case DLL_PROCESS_DETACH://进程剥离的时候
break;
}
return TRUE;
}
myfunc.h
#pragma once
//名称粉碎机制
//如果不声明extern "C"的导出方式的情况下,在导出表我们看到的名字就是一个碎片化的一个东西
//这个时候就没有办法去利用了
extern "C" __declspec(dllexport) int rkadd(int numberA, int numberB);
myfunc.cpp
#include "pch.h"
#include "myfunc.h"
int rkadd(int numberA, int numberB)
{
return numberA + numberB;
}