PE嵌入模板

编写一段代码,生成一个已经处理过重定位信息,同时所有的内容都在代码段里,并且没有导入表的PE程序,把这个程序嵌入到其他PE的相关位置,能够独立的运行,接下来是整理了2个模板,一个是HelloWorld的,另一个是通用模板LoadLibrary的模板。

开发环境masm32和vs2012,相关环境搭建我之前整理过[ http://blog.csdn.net/u013761036/article/details/52186683 ];

直接C++的话貌似不行,我用vs2015本地创建了一个空的项目,默认优化全开:

还是会有kernel32.dll。

接下来是模板1,功能是所有的东西都在一个独立的模块,弹出对话框,同时处理了全局变量的重定位问题。模板如下[代码是仿照Windows PE 权威指南,但是有些地方已经改过了,书上代码在我本地跑有问题,再获取Kernel32.dll地址的时候并不能成功得到地址。那个函数我已经重写了]:

;----------------------------------------
;补丁代码
;本段代码使用了API函数地址动态获取以及重定位技术
;程序功能:弹出对话框
;作者:Thinker
;开发日期:2017.4.30
;开发测试环境:vs2012+masm32、Win7 X64
;----------------------------------------.386
.model flat,stdcall
option casemap:noneinclude windows.inc;注意,此处不静态包含引入任何其他动态链接库,包括Kernell32.dll_ProtoGetProcAddress typedef proto :dword,:dword
_ProtoLoadLibrary    typedef proto :dword
_ApiGetProcAddress   typedef ptr _ProtoGetProcAddress
_ApiLoadLibrary      typedef ptr _ProtoLoadLibrary;----------------------------------------
;补丁代码中引入的其他动态链接库函数的声明
;----------------------------------------_ProtoMessageBox typedef proto :dword,:dword,:dword,:dword
_ApiMessageBox   typedef ptr _ProtoMessageBox;被添加到目标文件的代码从这里开始,到APPEND_CODE_END处结束
.code
jmp _NewEntry;以下内容为两个重要函数名
;几乎所有补丁都必须使用
szGetProcAddr db 'GetProcAddress',0
szLoadLib     db 'LoadLibraryA',0;----------------------------------------
;补丁代码中其他全局变量的定义
;----------------------------------------szUser32Dll   db 'user32.dll',0
szMessageBox  db 'MessageBoxA',0
szHello       db 'HelloWorldPE',0
;----------------------------------------
;获取kernel32.dll 的基地址
;----------------------------------------_getKernelBase proc;下面是Windows PE权威指南上的代码,获取Kernel32.dll地址失败,无奈我用自己之前的C++代码改了下,测试几次发现可以;local @dwRet
;pushad
;assume fs:nothing
;mov eax,fs:[30h]    ;PEB
;mov eax,[eax+0ch]   ;PEB_LDE_DATA
;mov esi,[eax+1ch]   ;InInitializationOrderModuleList
;lodsd
;mov eax,[eax+8]      ;Kernel32.dll的基地址
;mov @dwRet ,eax
;popad
;mov eax,@dwRet
;ret;之前写的C++代码改的[http://blog.csdn.net/u013761036/article/details/71006302]local @dwRet
pushad
assume fs:nothing
mov ebx, fs:[30h]          ;得到peb结构体的地址  mov ebx, [ebx + 0ch]       ;得到Ldr结构体的地址  mov ebx, [ebx + 0ch]       ;得到ldr.InLoadOrderModuleList.Flink 第一个模块,当前进程  mov ebx, [ebx]             ;得到第二个模块地址 ntdll.dll  mov ebx, [ebx]             ;得到第三个模块地址 kernel32.dll  mov ebx, [ebx + 18h]       ;得到第三个模块地址(kernel32模块的dllbase)        mov @dwRet, ebx
popad
mov eax,@dwRet
ret
_getKernelBase endp;----------------------------------------
;获取制定字符串的API函数的调用地址
;入口参数:_hModule 为动态链接库的基地址
;         _lpApi为API函数名称首指
;出口参数:eax 位函数在虚拟地址空间中的真实地址
;----------------------------------------
_getApi proc _hModule,_lpApi
local @ret
local @dwLen
pushad
mov @ret,0
;计算API字符串的长度,含最后的0
mov edi,_lpApi
mov ecx,-1
xor al,al
cld
repnz scasb
mov ecx,edi
sub ecx,_lpApi
mov @dwLen,ecx;从PE文件头的数据目录获取导出表地址
mov esi,_hModule
add esi,[esi+3ch]
assume esi:ptr IMAGE_NT_HEADERS
mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
add esi,_hModule
assume esi:ptr IMAGE_EXPORT_DIRECTORY;查找符合名称的导出函数名
mov ebx,[esi].AddressOfNames
add ebx,_hModule
xor edx,edx
.repeat
push esi
mov edi,[ebx]
add edi,_hModule
mov esi,_lpApi
mov ecx,@dwLen
repz cmpsb
.if ZERO?
pop esi
jmp @F
.endif
pop esi
add ebx,4
inc edx
.until edx >= [esi].NumberOfNames
jmp _ret
@@:;通过API名称索引获取序号索引,再获取地址索引
sub ebx,[esi].AddressOfNames
sub ebx,_hModule
shr ebx,1
add ebx,[esi].AddressOfNameOrdinals
add ebx,_hModule
movzx eax,word ptr [ebx]
shl eax,2
add eax,[esi].AddressOfFunctions
add eax,_hModule;从地址表得到导出函数地址
mov eax,[eax]
add eax,_hModule
mov @ret,eax_ret:assume esi:nothing
popad
mov eax,@ret
ret
_getApi endp;----------------------------------------
;补丁功能部分
;传入3个参数
;    _kernel :kernel32.dll的基地址
;    _getAddr:函数GetProcAddress地址
;    _LoadLib:函数LoadLibraryA地址
;----------------------------------------
_patchFun proc _kernel,_getAddr,_loadLib;----------------------------------------
;补丁代码局部变量定义
;----------------------------------------local hUser32Base:dword
local _messageBox:_ApiMessageBoxpushad;----------------------------------------
;补丁功能代码,下面例子弹出对话框
;----------------------------------------
;获取user32.dll的基地址
mov eax,offset szUser32Dll
add eax,ebxmov edx,_loadLib
push eax
call edx
mov hUser32Base,eax;使用GetProcAddress函数的首地址
;传入两个参数调用GetProcAddress函数
;获得MessageBoxA的首地址
mov eax,offset szMessageBox
add eax,ebxmov edx,_getAddr
mov ecx,hUser32Base
push eax
push ecx
call edx
mov _messageBox,eax;调用函数MessageBox
mov eax,offset szHello
add eax,ebx
mov edx,_messageBoxpush MB_OK
push NULL
push eax
push NULL
call edxpopad
ret_patchFun endp_start proclocal hKernel32Base:dword ;存放kernel32.dll基地址local _getProcAddress:_ApiGetProcAddress
local _loadLibrary   :_ApiLoadLibrary
pushad
;获取kernel32.dll的基地址
lea edx,_getKernelBase
add eax,ebx
call edx
mov hKernel32Base,eax;从基地址出发搜索GetProcAddress函数的首地址
mov eax,offset szGetProcAddr
add eax,ebxmov edi,hKernel32Base
mov ecx,edi
lea edx,_getApi
add edx,ebxpush eax
push ecx
call edx
mov _getProcAddress,eax;从基地址出发搜索LoadLibraryA函数的首地址
mov eax,offset szLoadLib
add eax,ebxmov edi,hKernel32Base
mov ecx,edi
lea edx,_getApi
add edx,ebxpush eax
push ecx
call edx
mov _loadLibrary,eax;调用补丁代码
lea edx,_patchFun
add edx,ebxpush _loadLibrary
push _getProcAddress
push hKernel32Base
call edxpopad
ret
_start endp;EXE文件新的入口地址_NewEntry:
call @F ;免去重定位
@@:pop ebx
sub ebx,offset @Binvoke _startjmpToStart db 0E9h,0F0h,0FFh,0FFh,0FFh
ret
end _NewEntry

最后的黑体是跳转用的。如果单独跑这个地方可以去掉,不然一条转都崩溃了,通常留着是为了嵌入到别的程序里之后,执行完之后跳转到原来程序入口地址等。

模板1的执行结果如下:

并没有导入表,同时相关字符串也没有存在数据段里:

代码段部分就是全部了,可以拷贝来独立的用。

模板2:和1类似,就是做了一个loadlibrary的模板,这样就和其他注入姿势一样了,只是加载一个dll,然后所有的东西在dll里面写就行了。Dllmain函数被调用的时候记得触发下自己就OK了。模板代码如下[一样书上的获取kernel32.dll代码无效,此处已经修正]。


;----------------------------------------
;补丁代码
;本段代码使用了API函数地址动态获取以及重定位技术
;程序功能:loadlibrary实现通用补丁代码
;作者:Thinker
;开发日期:2017.4.30
;开发测试环境:vs2012+masm32、Win7 X64
;----------------------------------------.386
.model flat,stdcall
option casemap:noneinclude windows.inc_ProtoLoadLibrary    typedef proto :dword
_ApiLoadLibrary      typedef ptr _ProtoLoadLibrary;被添加到目标文件的代码从这里开始,到APPEND_CODE_END处结束
.code
jmp _NewEntryszLoadLib     db 'LoadLibraryA',0
szDllName     db 'I.dll',0;----------------------------------------
;获取kernel32.dll 的基地址
;----------------------------------------
_getKernelBase proclocal @dwRet
pushad
assume fs:nothing
mov ebx, fs:[30h]          ;得到peb结构体的地址  mov ebx, [ebx + 0ch]       ;得到Ldr结构体的地址  mov ebx, [ebx + 0ch]       ;得到ldr.InLoadOrderModuleList.Flink 第一个模块,当前进程  mov ebx, [ebx]             ;得到第二个模块地址 ntdll.dll  mov ebx, [ebx]             ;得到第三个模块地址 kernel32.dll  mov ebx, [ebx + 18h]       ;得到第三个模块地址(kernel32模块的dllbase)        mov @dwRet, ebx
popad
mov eax,@dwRet
ret
_getKernelBase endp;----------------------------------------
;获取制定字符串的API函数的调用地址
;入口参数:_hModule 为动态链接库的基地址
;         _lpApi为API函数名称首指
;出口参数:eax 位函数在虚拟地址空间中的真实地址
;----------------------------------------
_getApi proc _hModule,_lpApi
local @ret
local @dwLen
pushad
mov @ret,0
;计算API字符串的长度,含最后的0
mov edi,_lpApi
mov ecx,-1
xor al,al
cld
repnz scasb
mov ecx,edi
sub ecx,_lpApi
mov @dwLen,ecx;从PE文件头的数据目录获取导出表地址
mov esi,_hModule
add esi,[esi+3ch]
assume esi:ptr IMAGE_NT_HEADERS
mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
add esi,_hModule
assume esi:ptr IMAGE_EXPORT_DIRECTORY;查找符合名称的导出函数名
mov ebx,[esi].AddressOfNames
add ebx,_hModule
xor edx,edx
.repeat
push esi
mov edi,[ebx]
add edi,_hModule
mov esi,_lpApi
mov ecx,@dwLen
repz cmpsb
.if ZERO?
pop esi
jmp @F
.endif
pop esi
add ebx,4
inc edx
.until edx >= [esi].NumberOfNames
jmp _ret
@@:;通过API名称索引获取序号索引,再获取地址索引
sub ebx,[esi].AddressOfNames
sub ebx,_hModule
shr ebx,1
add ebx,[esi].AddressOfNameOrdinals
add ebx,_hModule
movzx eax,word ptr [ebx]
shl eax,2
add eax,[esi].AddressOfFunctions
add eax,_hModule;从地址表得到导出函数地址
mov eax,[eax]
add eax,_hModule
mov @ret,eax_ret:assume esi:nothing
popad
mov eax,@ret
ret
_getApi endp_start proclocal hKernel32Base:dword ;存放kernel32.dll基地址
local _loadLibrary   :_ApiLoadLibrary
pushad
;获取kernel32.dll的基地址
lea edx,_getKernelBase
add eax,ebx
call edx
mov hKernel32Base,eax;从基地址出发搜索LoadLibraryA函数的首地址
mov eax,offset szLoadLib
add eax,ebxmov edi,hKernel32Base
mov ecx,edi
lea edx,_getApi
add edx,ebxpush eax
push ecx
call edx
mov _loadLibrary,eax;调用补丁代码mov eax,offset szDllName
push eax
call _loadLibrarypopad
ret
_start endp;EXE文件新的入口地址_NewEntry:
call @F ;免去重定位
@@:pop ebx
sub ebx,offset @Binvoke _start;jmpToStart db 0E9h,0F0h,0FFh,0FFh,0FFh
ret
end _NewEntry

运行结果:

代码段大小0x109,学习资料上的是优化到0x80,然而我照着写完MD各种运行不了,而且他里面定义了一堆变量最后根本没用上。获取Kernel32.dll部分的代码也是错的。FK浪费我太多时间调那个汇编代码,后来直接自己改了一个。上面的那个没有采取优化的姿势,需要用的,如果感觉大的话可以进行下汇编代码调整,优化下体积。

以后的PE嵌入通常用的也是这个通用的模板,因为只要通常Loadlibrary就OK了。当然如果想做反弹或者别的,对应的用这个姿势改就行了。目标就是不要有导入表,记得处理重定位,函数用到的数据记得是在代码段,不是放在数据段里面。

Windows PE变形练手2-开发一套自己的PE嵌入模板相关推荐

  1. Windows PE变形练手1-用PE自己的机器码修改自己的逻辑

    PE变形练手1-用PE自己的机器码修改自己的逻辑 就是找一个PE文件,用自己的部分代码部分覆盖或者而修改自己另一个代码部分的补丁姿势(现实中使用很少,极少数破解可以用到.这次例子目的是了解PE). 第 ...

  2. Windows PE变形练手3-把通用模板机器码直接覆盖目标PE

    把通用模板机器码直覆盖目标PE 这个地方真是尝试了好久,遇到很多坑点,Win PE那本书上的东西有点不够,也就直接写书上的例子会发现很多地方不是说的那样,里面提供的信息太少了,就比如里面并没有提被注入 ...

  3. HTML5响应式手机模板:电商网站设计——歪秀商城手机端开发静态页面HTML+CSS+JavaScript 手机模板wap 手机网站模板 企业手机网站模板...

    HTML5响应式手机模板:电商网站设计--歪秀商城手机端开发静态页面HTML+CSS+JavaScript 手机模板wap 手机网站模板 企业手机网站模板 手机网站模板 手机模板 响应式手机网站 ht ...

  4. HTML5响应式手机模板:电商网站设计——歪秀商城手机端开发静态页面HTML+CSS+JavaScript 手机模板wap 手机网站模板 企业手机网站模板

    HTML5响应式手机模板:电商网站设计--歪秀商城手机端开发静态页面HTML+CSS+JavaScript 手机模板wap 手机网站模板 企业手机网站模板 手机网站模板 手机模板 响应式手机网站 ht ...

  5. C++学习之路:适合C++新手的练手项目,高薪之路必备项目!

    市面上有很多C++的实战项目,从简单到进阶,学习每个项目都可以掌握相应的知识点. 如果你还是C++新手的话,那么这个C++的项目列表你可以拿去练手实战开发,毕竟学编程动手实践是少不了的! 如果你不知道 ...

  6. 有哪些适合新手练手的C/C++项目?

    1.(免费项目) C/C++ - C语言制作简单计算器 2.(会员项目) C/C++ - C语言实现通讯录 项目使用 C 语言完成一个简单的通讯录.会涉及到结构体.数组.链表等重要概念.此项目为实验楼 ...

  7. 安卓毕业设计-图书馆管理系统-新手练手项目

    图书馆管理系统 目的:1,用于毕业设计 2,用于用于新手的练手项目 开发环境:win7,android studio3.0.1,模拟器api:7.0.1 开发语言:Java 代码量:Java代码500 ...

  8. 10个综合管理系统类开源项目,速速拿去练手

    文章目录 1. Base Admin(练手 layui) 2. JeecgBoot(Vue) 2. zheng(MVC 分布式) 4. bm-rms(SSM 练手 Layui Easyui) 5. 办 ...

  9. java技术分享主题_Java开发入门:适合新手练手的Java项目(附源码下载)

    Java作为一门古老的语言,已有20年左右的历史,这在发展日新月异的技术圈可以说是一个神话.虽然不少人曾抱怨Java语言就像老太太的裹脚布,又臭又长,有时写了500行都不能表达程序员的意图. 但从市场 ...

最新文章

  1. oracle oats 安装,Mentor完整培训教程.pdf
  2. mysql中有哪些数值型函数_mysql数值型函数汇总
  3. html src 图片不显示图片,css中不用src也让图片显示的方法是什么?
  4. Substring with Concatenation of All Words
  5. jQuery使用toggleClass方法动态添加删除Class样式的方法
  6. JavaScript中split() 使用方法
  7. 【sklearn学习】随机森林分类、回归
  8. android 网卡监听,Android实时监听网络的变化
  9. drill apache_Apache Drill:如何创建新功能?
  10. python做接口自动化测试仪器经销商_Python接口自动化测试的实现
  11. 域用户更改密码提示拒绝访问_AD域中的ACL攻防探索
  12. 2020十大新消费人群
  13. 关于服务发现和负载均衡,你想知道的都在这儿
  14. ViewPage动态删除页面
  15. docker---dockerfile 编写优化
  16. 针对测试人员,这些业务安全漏洞你是否会测?
  17. 行走在网格之间:微博用户关系模型
  18. 计算机专业进铁路工资待遇,本科生刚进铁路局工资待遇汇总,仅供参考!
  19. matlab 函数,matlab 语法1
  20. HTTPS协议工作原理(SSL数字证书)

热门文章

  1. final 修饰方法参数
  2. 最新版本mysql jdbc驱动包获取表定义信息空指针异常处理方法
  3. C#把某个数组的一部分复制到另一个数组中的两种方法:Buffer.BlockCopy和Array.Copy...
  4. MySQL数据库服务器的架设
  5. 既之前的基础,先写个简单的PHP 与数据库 的数据交流
  6. javascript笔记:推荐使用“百度统计”并且拷贝百度统计的前端框架
  7. 偷懒的inline-block解决方法
  8. C# T 泛型类,泛型方法的约束条件用法
  9. 【JQuery】jQuery(document).ready(function($) { });的几种表示方法及load和ready的区别
  10. Linux:运行级别,root密码重置,救援模式,安装图形化界面