本节我们将演示如何实现远程注入的两种不同方案。方案一选择远程注入代码和数据,方案二选择远程注入DLL。
本节必须掌握的知识点:
无DLL远程注入
远程注入DLL
6.4.1 无DLL远程注入
实验四十五:无DLL远程注入(C语言实现)
我们尝试使用C语言实现一个无DLL远程注入的例子,支持32位和64位PE。
源码:
resource.h
//{
{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 remoteThread.rc 使用
//
#define ICO_MAIN 1000
#define DLG_MAIN 1000
#define IDC_INFO 1001
#define IDM_MAIN 2000
#define IDM_OPEN 2001
#define IDM_EXIT 2002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 4000
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
RemoteInject.rc
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ICO_MAIN ICON "dpatch.ico"
/
//
// Dialog
//
DLG_MAIN DIALOG 50,50,544,399
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "远程线程演示程序"
MENU IDM_MAIN
FONT 9,"宋体"
BEGIN
CONTROL "",IDC_INFO,"RichEdit20A",196 | ES_WANTRETURN | WS_CHILD | ES_READONLY
| WS_VISIBLE |WS_BORDER | WS_VSCROLL | WS_TABSTOP,0,0,540,396
END
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 169
END
END
#endif // APSTUDIO_INVOKED
/
//
// Menu
//
IDM_MAIN menu discardable
BEGIN
POPUP "文件(&F)"
BEGIN
menuitem "插入到PEHeader.exe(&O)...",IDM_OPEN
menuitem separator
menuitem "退出(&x)",IDM_EXIT
END
END
/
//
// AFX_DIALOG_LAYOUT
//
IDD_DIALOG1 AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // 中文(简体,中国) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
/
#endif // not APSTUDIO_INVOKED
EnableDebugPriv.c
#include <stdio.h>
#include <windows.h>
int EnableDebugPriv(const WCHAR *name)
{
HANDLE hToken; //进程令牌句柄
TOKEN_PRIVILEGES tp; //TOKEN_PRIVILEGES结构体,其中包含一个【类型+操作】的权限数组
LUID luid; //上述结构体中的类型值
//打开进程令牌环
//GetCurrentProcess()获取当前进程的伪句柄,只会指向当前进程或者线程句柄,随时变化
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
printf("OpenProcessToken error\n");
return -8;
}
//获得本地进程name所代表的权限类型的局部唯一ID
if (!LookupPrivilegeValue(NULL, name, &luid))
{
printf("LookupPrivilegeValue error\n");
}
tp.PrivilegeCount = 1; //权限数组中只有一个“元素”
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //权限操作
tp.Privileges[0].Luid = luid; //权限类型
//调整进程权限
if (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
printf("AdjustTokenPrivileges error!\n");
return -9;
}
return 0;
}
RemoteInject.c
/*------------------------------------------------------------------------
FileName:remoteThread.c
实验45:远程线程注入演示程序
功能:目标是在进程PEHeader.exe中远程注入一段代码和数据,运行并显示"Welcome to PE!"对话框。
测试步骤:当PEHeader.exe运行时,运行remoteThread.exe,文件菜单---插入到PEHeader.exe
(c) bcdaren, 2024
-----------------------------------------------------------------------*/
#include <windows.h>
#include <strsafe.h> //StringCchCopy
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
#include <Richedit.h>
#include <tchar.h>
#include <string.h>
#include "resource.h"
//使用typedef给函数指针类型一个别名,函数指针存储函数地址
typedef FARPROC(__stdcall *_ApiSuspend)(HANDLE);
typedef HMODULE(__stdcall *_ApiResume)(HANDLE);
typedef HMODULE(__stdcall *_ApiLoadLibraryA)(LPCSTR);
_ApiSuspend _suspendProcess;
_ApiResume _resumeProcess;
//INJDATA(注入的数据)
typedef LRESULT(WINAPI *MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, UINT);
typedef struct {
HWND hwnd; // handle to edit control
MESSAGEBOX fnMessageBox; // pointer to user32!MessageBox
CHAR psText[128]; // buffer that is Text
} INJDATA;
extern int EnableDebugPriv(const WCHAR *);
BOOL CALLBACK ProcDlgMain(HWND, UINT, WPARAM, LPARAM);
BOOL _patchPEInfo();
void _Init();
HANDLE hInstance;
HWND hWinMain, hWinEdit;
//ThreadFunc(注入的代码)
static DWORD WINAPI ThreadFunc(INJDATA *pData)
{
pData->fnMessageBox(pData->hwnd, (LPCTSTR)pData->psText, NULL, MB_OK);
return 0;
}
// This function marks the memory address after ThreadFunc.
// int cbCodeSize = (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
static void AfterThreadFunc(void)
{
return;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
const TCHAR szDllEdit[] = TEXT("RichEd20.dll");
const TCHAR szClassEdit[] = TEXT("RichEdit20W");//peinfo.rc中定义
const TCHAR szNtdll[] = TEXT("ntdll.dll");
const CHAR szSuspend[] = "ZwSuspendProcess";//函数名需要定义为ASCII字符
const CHAR szResume[] = "ZwResumeProcess";
const TCHAR szErr3[] = TEXT("Error happend when getting address.");
HMODULE hRichEdit, hNtdll;
hRichEdit = LoadLibrary((LPCWSTR)&szDllEdit);
hNtdll = LoadLibrary((LPCWSTR)&szNtdll);
_suspendProcess = (_ApiSuspend)GetProcAddress(hNtdll, szSuspend);
if (!_su