前段时间一直学习逆向工程核心原理,由于缺少WINAPI只是,后面的
内容学起来有些抽象,于是反回去大致扫了一下《Windows核心编程》
花了些时间写了个DLL注入器。
基本原理
进程对象在windows中,地址空间基本都是相对独立的,一
个进程无法操作其他进程的空间,但是通过创建远程进程的线程,在原
来进程的主线程之上添加一个线程,该线程属于远程进程,却又是我们
的代码,所以可以在远程进程中实现我们的代码。
DLL注入利用了这个特点,目的是在运行的进程强制调用为WINAPI函数
LoadLibrary()载入我们自己编写的dll,dll会被插入进程的内存空间中,由
于dll第一次被载入地址空间,会调用其自身给DllMain函数,以初始化,利
用这个特性,我们可以做到,在目标进程中调用我们的代码。
#include "stdafx.h"
#include<Windows.h>
#include<iostream>
using namespace std;
DWORD WINAPI myfunc(PVOID);
/*PROCESS_ALL_ACCESS 全部进程权限 PVOID VirtualAllocEx(handle,pvoid,size_y,dword,dword)在指定进程分配地址。
_CREATE_PROCESS 创建进程的权限 注意在本函数内创建的函数地址,作为远程线程传入地址,结果不可知!!!违规访问。
_CREATE_THREAD 创建线程的权限
_DUP_HANDLE
_VM_OPERATION 操作进程内存空间
_VM_READ 读取进程内存空间
_VM_WRITE写入进程内存空间
*/
//bin...进程句柄是否可被继承TRUE / FALSE
//dwprocessid被打开的进程
int _tmain(int argc, _TCHAR* getid[])
{
if(getid[1] == NULL)
{
cout<<"make sure you send the right pid or dll!!!"<<endl;
return 0;
}
DWORD pid = atoi(getid[1]); //权限+句柄继承性+pid
HANDLE victim = OpenProcess(
PROCESS_CREATE_THREAD|
PROCESS_VM_OPERATION|
PROCESS_VM_WRITE,
FALSE,
pid);
if(victim == NULL)
{
cout<<"cant open the process!!!"<<endl;
return 0;
}
else
cout<<"open successed!!!"<<endl;
HANDLE MYTHREAD;
int prama;
PTHREAD_START_ROUTINE pfnthread = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(TEXT("Kernel32")),"LoadLibraryA");
//virtualfreeex可以释放内存。第一个进程句柄,表示在哪个进程句柄中执行该操作。
/* BOOL WriteProcessMemory(handle,pvoid,lpcvoid,size_t,size_T*)读写目标进程空间地址,目标句柄,进程中的地址,本地内存地址,传输的弟子结束。
实际传输字节数*/
char buf[50] = {0};
cout<<"entel the dll name"<<endl;
gets(buf); //buf保存dll路径
printf("\ntry %s \n",buf);
int cnt = 0;
while(buf[cnt] != '\0')
{
cnt++;
}
cnt++;
cout<<cnt<<endl;
SIZE_T words;
PVOID pos = VirtualAllocEx(victim,NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//立即申请,即可读,也可写。
if(pos != NULL)
cout<<"success alloc"<<endl;
else
{
cout<<"failed ALLoc"<<endl;
return 0;
}
BOOL state = WriteProcessMemory(victim,pos,buf,cnt*sizeof(char),&words);
cout<<words<<endl;
if(state == TRUE)
cout<<"success write"<<endl;
else
{
cout<<"failed write"<<endl;
return 0;
}
MYTHREAD = CreateRemoteThread(victim,NULL,0,pfnthread,pos,0,NULL); //传入正确的loadlibray函数,并且传入正确的vitrual创建的
//内存
if(MYTHREAD != NULL)
{
cout<<"thread created!!"<<endl; //注意直接加载函数时,需要确定位置,编译链接时有宏,否则分清楚unicode和ansc版本!!!1
}
else
{
cout<<"thread failed!!"<<endl;
return 0;
}
return 0;
}
本例在VS 2010编译器,ascii字符下编译通过,供参考。
重点在于,虚拟地址的分配,必须在对象进程中开辟内
存,否则访问地址结果将是不可知的!!!!!
测试用的是逆向工程核心原理中的dll,在后台下载一个index.html
注入目标
开始注入
成功下载index.html
版权声明:本文为jazrynwong原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。