dll注入基础教程_第1页
dll注入基础教程_第2页
dll注入基础教程_第3页
dll注入基础教程_第4页
dll注入基础教程_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

首先要明白什么是线程说到线程就不得不提到进程SDK文档里是这样描述的进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的代码、数据和其他系统资源。一个进程包含了一个或者多个运行在此进程内的线程。说白了,其实进程就是一个磁盘上的程序载入内存执行后的东西打开任务管理器看看,里面有好多进程...从定义上看出进程一定要有线程,线程是进程内存中的独立实体。讲了这么多废话其实就是想说程序运行后就变成了进程,你的代码由线程来执行。回到正题上,线程插入是什么呢?就是把一个线程弄到别的进程执行你也许觉得奇怪,自己不是有个进程好好的吗?其实这个作用大了,先说说开头提到的木马一来,有些比较由经验的用户有时会打开任务管理器,发现陌生进程?!想想你的木马还能活吗?那么插入Explorer等关键进程,你还想用电脑的话最好不要杀那个进程(不信试试)二来,大家现在都装防火墙了,网络连接经常会被虑掉,木马岂不是没用了?好,插入IE,防火墙想虑?除非你不想看网页当然,还有很多用处,比如插入系统级别的进程,哈哈,我们有RingO权限了,(不要告诉我你不知道Ring0...就是连物理内存都可以写的超级权限)HookAPI也需要把代码注入别的进程知道了他的作用想知道怎么实现吧?别着急,慢慢来首先,这个应该属于系统编程,系统编程就不能不知道APIAPI是什么?简单点讲就是Windows为我们提供的一些函数,利用他们我们可以做很多事情Delphi花了很大力气用VCL还有一些乱七八糟的类把让我们可以尽量不要API所以会编程序但不了解API还是可能的API被封装在kernel32.dll、user32.dll等动态链接库里,程序使用时候把DLL映射到自己的内存了编写的时候我们通常需要从DLL导出这些函数functionBeep;external'kernel32.dll'name'Beep';这样导出一个beep函数当然,实际上不要这么麻烦Delphi已经把这些导出声明写在一些单元里面了(比如windows单元)useswindows后就可以直接用了(而且建立窗口时候默认就会引用很多单元)所以实际上我们可以直接用的这个理解一下就好了开始讲线程插入了一般来说线程插入有2种方法DLL注入直接的远程线程插入DLL注入编写的时候比较简单,方法也多,但有个缺点进程会多出个模块来,可能被发现远程线程是直接修改对方内存的方法,虽然隐蔽性好,但是不小心可能会出点问题,比如你让不能有界面的进程弹出个窗口,不能上网的进程开个端口,那就等着系统崩溃吧今天重点讲DLL注入首先要知道什么是DLL,dll就是动态链接库,大家应该知道吧?怎么编写DLL呢?和写普通程序差不多是一样的新建一个工程,选DLLWizard发现了吧?除了program改成library剩下几乎是一样的,只是需要程序加载他的入口点我们先编写个简单的DLLlibraryTestDll;usesWindows;{$R*.res}procedurefunc_a;beginMessageBox(0,'Ilovedelphi','FunctionformTsetDLL',0);end;procedurefunc_b(MSG:pchar);beginMessageBox(0,MSG,'FunctionformTsetDLL',0);end;beginfunc_a;func_b('Ilikeittoo!');end.就是那个testdll.dpr看得懂吧,弹出2个信息框好了保存下,F9运行••出错,哈哈,DLL是不能直接运行的那怎么办?编译下(按过F9就不用了,也会编译好)看见那个DLL了吧?我们弄个程序加载它的入口点新建一个普通程序加一个按钮按钮事件只要写一句loadlibrary('testdll.dll');MainShow.dpr运行,单击按钮,怎么养?弹出东西了吧当然DLL还可以做函数库,资源库等今天暂不讨论现在DLL懂得写了吧?就是program改成library而已你可以写自己的程序了DLL会写了,现在的问题就是怎么注入了我们目的只是让对方的程序运行一句loadlibrary('testdll.dll');而已一切就OK了通常有这么几种注入方法利用全局消息钩子Win32下程序一般都要用收发消息用钩子函数下全局钩子,程序收到任何消息都加载我们的DLL的入口点当然,用这种方法DLL进入后要判断自己是不是被插进目标进程是的话,执行代码不是退出这个方法很麻烦但通用性很好,只要WINDOWS都可以用(但是有的系统进程消息是勾不住的,所以注入不了)早期的DLL注入大部分是用这个原理实现的写注册表写 HKEY_LOCAL_MAHINE\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit_DLLs但是只能是NT下,而且必须是调用过user32.dll(Windows的一个内核,只要有界面的程序都调用它)的程序,在开机后所有程序会自动加载DLL,但是这个dll不能被卸载,而且不能调用某些函数,不然系统会挂掉(有危险性哦)不推荐使用利用远程线程注入来实现DLL注入只要能打开句柄,就能成功(强吧?)而且实现起来比较简单缺点就是9X内核的有点难度(也不是很困难)我们今天就讲利用远程线程注入来实现DLL注入吧!你可能要问,既然刚才说了远程线程可以直接注入一个线程,为什么还要多此一举反过来再调用DLL呢?这是因为,远程线程技术一般是直接对目标程序的内存进行操作我们知道不同程序的虚拟内存是不一样的所以很多函数的地址不一定一样而程序运行的时候实际上是Call函数地址进行函数调用的所以我们要注意计算很多偏移之类的这是非常烦琐的事情而且像上面说的让不能有界面的进程弹出个窗口,那就不好玩了而DLL呢?DLL调用时其实是被映射到进程内存里面DLL拥有自己的导入表、资源、函数等东西,实际上就是一个完整的程序映入内存后和执行一个程序效果是一样的这样我们就不用考虑那些乱七八糟的东西,只要安心的写功能即可好了,要明白远程线程首先当然要把程序本地线程搞清楚了不知道大家编多线程程序的时候是不是都用tthread类?反正我是不喜欢那个我们看看Windows给我们的原始API吧(tthread类也是用它写的)functionCreateThread(lpThreadAttributes:Pointer;//安全指针一般nil就可以了dwStackSize:DWORD;//线程初始化尺寸,一般用0,获得与主线程一样尺寸(不够自己会增加,别担心)lpStartAddress:TFNThreadStartRoutine;//一个指向要执行线程函数的指针,这个函数必须遵守Stdcall约定,并且可带一个参数,参数必须是指针类型lpParameter:Pointer;//函数的参数dwCreationFlagS:DWORD;//控制创建标志,用0表示线程立刻执行varlpThreadId:DWORD)//返回标识变量我觉得没什么用,反正句柄都有了:THandle;//返回线程的句柄stdcall;//标准调用Windows下API—般都是标准调用大家先看下看起来似乎比较复杂,等下举个例子我们把DLL源码里面的func_b拷到刚才那个EXE上稍微修改下procedurefunc_b(MSG:pchar);stdcall;beginMessageBox(0,MSG,'FunctionformTsetDLL',0);sleep(lOOOO);//线程暂停N久(不超过10s)end;加上2个按钮第一个procedureTForm1.Button2Click(Sender:TObject);beginfunc_b('123');end;第二个procedureTForm1.Button3Click(Sender:TObject);vartid:longword;//放返回值,不放她不让执行,郁闷str:pchar;//便于获得pointerbeginstr:='123';createthread(nil,0,@func_b,//函数名前面加@是得到函数指针pointer(str),//虽然str也是指针,但是delphi就是要pointer型的,那就转一下类型0,tid);//tid纯属放着占格式的,一般我们用不到end;//上面CreateThread看得懂吧,几乎都是默认设置,以后套下去用就是了实际上都是调用func_b,只是第二个过程用了信新线程但是效果是不一样的第一个按钮按下弹出窗口后,程序卡死了(暂停10000)第二个却不会为什么呢?我们可以这样理解窗口看做一个主线程,执行func_b,弹出窗口,然后主线程挂起,于是卡死了而第二个过程创建一个新线程,新线程执行func_b,弹出窗口,挂起10000,但是由于主线程没有挂起,所以看起来关掉窗口后没什么事情发生(实际上那个线程还在偷偷执行,直到线程代码运行完,只是它卡死不会影响你)这个如果明白了那么下面就容易理解了看看这个函数functionCreateRemoteThread(hProcess:THandle;lpThreadAttributes:Pointer;dwStackSize:DWORD;lpStartAddress:TFNThreadStartRoutine;lpParameter:Pointer;dwCreationFlags:DWORD;varlpThreadId:DWORD):THandle;stdcall;除了函数名不一样,下面的参数多了个hProcess:THandle;,剩下的完全一样呵呵,这个东西就是本节课的关键了先看函数名就知道是干什么用的了‘创建远程线程'用法和刚才基本一致就是hProcess:THandle是什么呢?这里要填的是被注入线进程的句柄什么是句柄?打个比方,对象是一个门,句柄就是那个把手,通过句柄我们可以对门进行操作也就是说我们利用句柄来操作某些东西(包括进程、线程等等)你有没有注意到,CreateThread和CreateRemoteThread都返回一个THandle,也就是线程的句柄还有loadlibrary也会返回DLL的句柄,我们可以利用他们对相关对象进行操作那么怎么获得进程句柄呢?一般采用先得到进程PID再用下面的函数取得句柄functionOpenProcess(dwDesiredAccess:DWORD;//访问标志一般填写PROCESS_ALL_ACCESS,这样这个句柄可以获得最大操作权限bInheritHandle:BOOL;//可否继承,这个跟子程序有关,无所谓了,填false和true都可以,反正我们自己能操作久可以dwProcessId:DWORD)://要获得句柄的进程IDTHandle;stdcall;//返回句柄有时候会返回0,说明打开句柄失败了一般是你的权限不够(比如你想对Winlogon这些系统级程序操作)这时候我们需要提升权限一般Debug权限就可以了(其实操作权限里面最高了)提升的过程我写好了直接调用就可以了(修改进程令牌到Debug级别,为什么这样写这里不详细讲了,自己去网上搜索下)procedureGetDebugPrivs;varhToken:THandle;tkp:TTokenPrivileges;retval:dword;beginIf(OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGESorTOKEN_QUERY,hToken))thenbeginLookupPrivilegeValue(nil,'SeDebugPrivilege',tkp.Privileges[0].Luid);tkp.PrivilegeCount:=1;tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken,False,tkp,0,nil,retval);end;end;不会晕吧?应该记得我刚才提到了要PID,那怎么得到呢?一般用FindWindow和GetWindowThreadProcessId配合的到这样写先varPid:longword;//储存那个PIDGetWindowThreadProcessId(FindWindow('Notepad',nil),@PID);这样就找到笔记本的PID,再如'Shell_TrayWnd'可以找到Explorer的窗口类名据说可以用SPY++查询,不过这东西我没见过,呵呵当然还可以枚举进程判断进程名等等这个先告一段落。好了,拿Windows的笔记本下手吧procedureTmyForm.Button4Click(Sender:TObject);varh:longword;//PID和THandle的类型其实都是longword,改个名字而已,所以可以通用beginwinexec('notepad',1);//运行笔记本GetWindowThreadProcessId(FindWindow('notepad',nil),@h);//得到Pid存在hh:=OpenProcess(PROCESS_ALL_ACCESS,False,h);//得到handle存在h,后面那个是变量pid,算完放到前面的h是句柄(两个不同的东西,只是类型一样而已)sleep(2000);//等2秒TerminateProcess(h,O);//关闭笔记本,h是那个句柄,0表示正常退出end;运行起来就是打开一个笔记本,大约2s狗关掉它不知道大家看懂了没有,没有不要紧,只是为了证明我们可以拿到一个课操作的进程句柄好像万事具备了吧?那试试远程线程了吧再建一个按钮前面的还是这样写,再把那个建立线程的拷过来改成CreateRemoteThread加上h参数procedureTmyForm.Button5Click(Sender:TObject);varh:longword;tid:longword;str:pchar;beginstr:='123';winexec('notepad',1);GetWindowThreadProcessId(FindWindow('notepad',nil),@h);h:=OpenProcess(PROCESS_ALL_ACCESS,False,h);CreateRemoteThread(h,nil,0,@func_b,pointer(str),0,tid);end;运行起来笔记本出来了,对话框也出来了...可是对话框却不是我们弄的那个,是个报错的看看写了什么内存'0x00000000'不能为'writen'为什么呢?记得我刚才说的么远程线程是在别的程序里运行一个线程相当于让里一个函数执行CreateThread所以,函数的地址不一定是一样的,更何况笔记本里面怎么可能会有func_b这个我们自己写的函数呢这么一来当然要出错了这下傻了,那怎么注入我们要的函数呢?记得我们要讲什么吗?-利用远程线程进行DLL注入我们可以把函数写在DLL里面,用远程线程让目标进程加载它这样函数就执行了我们只要想办法让对方程序loadlibrary('testdll.dll');那就OK了看看LoadLibrary的原型functionLoadLibrary(lpLibFileName:PAnsiChar):HMODULE;stdcall;你应该发现了它和线程要求的函数格式几乎一样参数是指针型PAnsiChar就是pchar,—个指向字符串的指针返回HMODULE,HM0DULE实质是longword(改个名字而已)那就远程运行它吧这时候你可能会想,LoadLibrary的地址要怎么得到呢?要知道,LoadLibrary是一个API(在Kernel32.dll里面),实际上,每个Win32程序都需要里面的函数所以,大部分程序运行代码前会装入这个DLL,把里面的函数映射到自己的内存了这么一来,只要是这个DLL里面同一个函数在所有的进程里地址都是一样的哈哈,这样就容易了地址我们一般用GetProcAddressfunctionGetProcAddress(hModule:HMODULE;//模块句柄,DLL被加载后就成立模块,等下告诉大家怎么得到这个lpProcName:LPCSTR//函数在DLL中的导出名LoadLibrary实际上是LoadLibraryA//这个大家看看DelphiWindows单元的源码就知道了):FARPROC;stdcall;//返回指针那些类型看得乱乱的吧,不要管他们,在Delphi上不鼠标停在函数上,类型的原型就出来了好了现在是怎么得到那个模块的句柄的问题用GetModuleHandlefunctionGetModuleHandle(lpModuleName:PChar)//模块名,DLL被加载后就成立模块,所以就是DLL的文件名了:HMODULE;stdcall;//返回模块句柄好了。知道了这些得到函数地址就容易了GetProcAddress(GetModuleHandle('KERNEL32.DLL'),'LoadLibraryA');一句搞定问题似乎都解决了吧?先别高兴,不要忘记了,它还带了个参数,就是那个DLL的名字参数类型是一个指向字符串地址的指针这个是个大问题,一来你不能保证别人的程序内存里有这个字符串二来有你也不知道他的位置,这可怎么办呢?自己写!我们把那个字符串写到对方内存里呵呵,很霸道的方法,但的确是个好方法不废话了,开始我们首先要在目标进程申请一块内存,以便把那个参数写进去申请内存用VirtualAllocEx,看看它的原型functionVirtualAllocEx(hProcess:THandle;//目标进程句柄,这个不用说了吧lpAddress:Pointer;//分配内存位置,一般用nil,这样会在系统认为最合适的位置分配dwSize:DWORD;//分配的地址范围,也就是大小了flAllocationType:DWORD;//如何分配地址,一般用MEM_COMMIT为指定空间提交物理内存flProtect:DWORD//该段内存的保护类型,PAGE_READWRITE表示可读可写):Pointer;stdcall;//返回内存地址,哈哈,这就是我们要的那个参数的指针了好了,分配完内存当然是要把我们的数据写过去了这时候需要用到WriteProcessMemory来写进程的内存functionWriteProcessMemory(hProcess:THandle;//目标进程句柄constlpBaseAddress:Pointer;//要写的内存地址,就填我们那个参数的指针lpBuffer:Pointer;//数据的地址,我们把字符串存这里,让他拷nSize:DWORD;//要拷贝的数据长度//字符串在Windows定义是以null(就是16进制的0)结尾的//所以长度就是字符串的长度+1varlpNumberOfBytesWritten:DWORD)//返回的什么东西,没什么用:BOOL;stdcall;//返回成功或失败我们来写个完整的代码吧procedureTmyForm.Button6Click(Sender:TObject);varh:longword;//放句柄,中间顺便暂放下PIDtmp:longword;//这个专门来占格式收集垃圾DllName:pchar;Mysize:longword;//放字符串长度Parameter:pointer;//放那个参数的指针(位置在目标进程内)beginDLLName:='Testdll.dll';Mysize:=strlen(Dllname)+1;winexec('notepad',1);GetWindowThreadProcessId(FindWindow('notepad',nil),@h);h:=OpenProcess(PROCESS_ALL_ACCESS,False,h);Parameter:=VirtualAllocEx(h,nil,Mysize,MEM_COMMIT,PAGE_READWRITE);WriteProcessMemory(h,Parameter,Pointer(DllName),MySize,tmp);CreateRemoteThread(h,nil,0,GetProcAddress(GetModuleHandle('KERNEL32.DLL'),'LoadLibraryA'),Parameter,0,tmp);end;又看到那两个熟悉的对话框了哈哈,这么说我们成功了如把那个DLL换成其他的功能,那就..

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论