首页
社区
课程
招聘
[原创] 小试牛刀·手动构建HelloWorld弹窗可执行文件
发表于: 2021-4-6 04:01 9441

[原创] 小试牛刀·手动构建HelloWorld弹窗可执行文件

2021-4-6 04:01
9441

参照书籍:《Windows PE权威指南》;
文件:附件中(文件密码:apebro);
使用工具:WinHex、CFF、StudyPE+、OD、IDA、MSDN;

1、有时候会需要干净的小exe文件进行魔改;

2、无关紧要的地方就用CC(int3)或者90(nop)的地方覆盖了;

3、关键位置我都用红框给框起来了;

使用WinHex手动构建一个PE;

image-20210406005843355image-20210406005912096

image-20210406010248744

因为是手动构造,所以就舍弃了DOS头下面的一堆垃圾数据了;

image-20210406010505752

image-20210406011433020

image-20210406011722167

image-20210406012009509

最重要的四个参数标注出来,这四个数都是有来头的,并不是瞎设的;

image-20210406012338302

这分别是:

image-20210406012855971

这时候就可以明白代码页节表的文件起始地址就是从0x00000200开始的;

这个时候我们需要构建我们的导入表了,因为.text节区空间很大,所以也放里面了;

首先在导入表节表目录处设置一下。

image-20210406025507546

image-20210406013634693

这里解释一下:

导入符号表为零,系统就会直接引用IAT表,这是系统特性;

然后看导入链接库名(RVA:0x00001030,FOA:0x00000230),这是一个C语言类型的字符串,\0结尾,得到导入的动态库名为user32.dll

再看IAT表间接地址(RVA:0x00001050,FOA:0x00000250),得到IAT表地址(RVA:0x00001040,FOA:0x00000240);

这里就是一个重点了,函数名字符串并不是从0x00000240开始的,而是从0x00000243开始的。因为这里的结构类型如下:

所以得到函数名MessageBoxA

用OD随便打开一个非我们正在构建的可执行文件,因为我们手动构建的PE文件有些字段被设置,所以OD并不能正常打开,除非有插件;

然后准备进行以下结构的汇编代码插入;

这里的CaptionText两个字符串我们需要先找个地方存放;

image-20210406020738686

然后根据约定,补齐0x200的倍数;

这里我们补齐到0x3FF;

image-20210406030317339

然后选定代码存放位置;

image-20210406030449216

这里的0x00000280FOA,我们需要换算成RVA,也就是0x00001080;

Optional Header中找到OEP,这里的OEP是字段,并不是脱壳时说的原始入口点;

image-20210406030922046

保存后,执行文件;

image-20210406031049278

但是问题不大,我们要的就是如此,别退掉这个窗口;

image-20210406031321364

首先是文件地址;

image-20210406031651319

然后是内存地址,这个我们要看我们导入表的节表内容,查看加载地址;

image-20210406031857592

既然导入表没问题了,我们剩下的就是要完善我们的程序了。

image-20210406032227161

进入后很明显不是正常的入口地址;

image-20210406032306787

问题不大,莫慌;

image-20210406033153706

image-20210406033338641

然后开始,我们要写入我们的代码了;

image-20210406033945458

结果就是如此;

image-20210406034710690

image-20210406034743290

保存后退出所有界面,找到这个test1.exe文件,双击运行;

image-20210406034832624

image-20210406034953182

一觉醒来,坛主大佬亲临,并且指出了并不能跨平台的问题;

image-20210406144002353

是可以运行的;

一闪而过,可见的是hello world!字符串并没有传进去;

经过多方查找问题,终于找到问题所在;

需要将图中框起来的位置(Win32VersionValue字段)用0填充;

image-20210406174511398

就运行起来了;

image-20210406175542890

image-20210406145250106

也是能运行起来的;

这里我就懵逼了,坛主大佬指的到底是哪里问题呢,还是先自己找一下,那就先复习一下导入表吧;

这里数据目录找导入表上面有,我就不赘述了;

我再复习了一下导入表的导入流程(以test1为例);

image-20210406145956340

这里的结构是:

说太多容易乱,我直接就开始白话了;

这里要说一下的是桥1指向的地址列表被称为INT表,桥2指向的地址列表被称为IAT表;

操作系统如何读取PE的导入表

image-20210406155627168

这里提一句,如果目标为0x00000000,那么就是continue操作,搜索下一个导入表,这里涉及一个无效导入表的奇技淫巧;

image-20210406160056003

这里提一句,加载字符串时候,不能超过260个字节,如果超过了,即使是有效导入表,也会被操作系统拒绝加载,这里涉及一个反调试手段的奇技淫巧;

image-20210406165154120

而FOA0x00000250这个位置在加载后会被重定位API地址;

如果IAT00000000,系统判断是非法PE,直接停止后续运行;

找到的字符串,前一个word的函数序号,操作系统不参考,所以我填了nop(90);

找到了函数名(MessageBoxA),执行GetProcessAddress,如果错误了,就中断执行;

如果执行成功了,就访问IAT表(RVA0x00001050->FOA0x00000250)地址,并修正地址;

image-20210406171819699

修正后:

image-20210406171905494

整个流程理下来,还是没搞清楚大佬说的写死IAT是什么意思;

现在只能去反汇编一个C语言写的MessageBox程序,一探究竟;

image-20210406173050970

image-20210406174050555

打开IDA看一下,这里是RA地址;

image-20210406174143932

image-20210406174202940

所以,编译器制作的PE文件也只是通过IAT跳转,系统加载的时候通过修正,得到当前系统的函数地址。

故并不存在跨平台问题

手动制作PE文件是个非常有意思的事情;

原本只是为了写另外一篇帖子,发现需要用到这个,如果写在一起又太臃肿,所以单独水一贴吧;

关于大佬说的写死IAT的跨平台问题,我并没有找到问题,如果有大佬能指正,感激不尽;

 
 
 
 
1. `镜像基址`:`0x00400000`;
2. `镜像对齐`:`0x00001000`;
3. `文件对齐`:`0x00000200`;
1. `镜像基址`:`0x00400000`;
2. `镜像对齐`:`0x00001000`;
3. `文件对齐`:`0x00000200`;
 
 
 
IMAGE_IMPORT_BY_NAME struct{
    word Hint;        // 函数编号;
    dword Name;        // 函数名字符串;
}
IMAGE_IMPORT_BY_NAME struct{
    word Hint;        // 函数编号;
    dword Name;        // 函数名字符串;
}
push    0              
push    offset Caption
push    offset Text    
push    0              
call    MessageBoxA
retn
push    0              
push    offset Caption
push    offset Text    
push    0              
call    MessageBoxA
retn
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-4-8 15:35 被平头猿小哥编辑 ,原因: 上传附件
上传的附件:
收藏
免费 4
支持
分享
最新回复 (11)
雪    币: 8178
活跃值: (4131)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
围观,前排点赞!
2021-4-6 11:35
1
雪    币: 47147
活跃值: (20415)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
call [00401050] //你直接写死IAT了,不能跨平台,建议 将整个 输入表重建一份
2021-4-6 11:43
1
雪    币: 2810
活跃值: (2913)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
嗯,感谢大佬指出这个问题。
2021-4-6 13:52
0
雪    币: 2810
活跃值: (2913)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
kanxue call [00401050] //你直接写死IAT了,不能跨平台,建议 将整个 输入表重建一份
嗯,感谢大佬指出这个问题。
2021-4-6 13:53
0
雪    币: 2810
活跃值: (2913)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
6
kanxue call [00401050] //你直接写死IAT了,不能跨平台,建议 将整个 输入表重建一份
大佬你好,我找了一下并且尝试探索,并不存在IAT表写死的问题,并且把过程补帖在这个帖子下方。还请指点问题所在;
2021-4-6 18:03
0
雪    币: 47147
活跃值: (20415)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
7
平头猿小哥 大佬你好,我找了一下并且尝试探索,并不存在IAT表写死的问题,并且把过程补帖在这个帖子下方。还请指点问题所在;
你之前文章中没有提到IMAGE_IMPORT_DESCRIPTOR 结构,以为没构造导入表,直接IAT里跳到相应函数中去了。
2021-4-8 11:22
0
雪    币: 2810
活跃值: (2913)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
嗯嗯,是我没有讲清楚,是我生疏了,感谢大佬,让我又复习了一边导入表;
2021-4-8 12:31
0
雪    币: 2810
活跃值: (2913)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
9
kanxue 你之前文章中没有提到IMAGE_IMPORT_DESCRIPTOR 结构,以为没构造导入表,直接IAT里跳到相应函数中去了。
嗯嗯,是我没有讲清楚,是我生疏了,感谢大佬,让我又复习了一边导入表;
2021-4-8 12:31
0
雪    币: 2246
活跃值: (3773)
能力值: ( LV6,RANK:81 )
在线值:
发帖
回帖
粉丝
10
这让我想起当初用针戳光盘雕出win7系统盘的往事
2021-4-12 15:24
0
雪    币: 2810
活跃值: (2913)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
11
KingSelyF 这让我想起当初用针戳光盘雕出win7系统盘的往事[em_86]
哈哈,大佬你这个操作堪比用机器码写操作系统呀
2021-4-12 20:07
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12

1

最后于 2022-6-26 15:32 被你云龙编辑 ,原因:
2022-6-26 14:44
0
游客
登录 | 注册 方可回帖
返回
//