能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(基础版)
muxicao
(⊙o⊙)…
我还有个问题,
在Shell中,对系统的导入表IAT进行了填充,但是除此之外没有其他操作(比如像更改原程序的重定位指针到Shell),那么系统在加载被加壳程序的时候,应该还会进行导入 ...
这个壳写的是时候是很久以前了,具体细节忘了。大概思路是:加壳后的程序的导入表是shell部分的,由于shell部分不需要系统去对导入表操作,所以在PE结构中就把导入表抹去了。而源程序的导入表是shell部分来填充,shell部分模拟系统对导入表的操作。
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(扩展版)
加壳后执行程序是先运行的shell部分的代码,shell部分代码用到的函数是手动获取的函数地址,所以用不到导入表,就把PE信息里的导入表给删了。。。
这样别人就不会直接用工具看到你的PE文件的导入表了,这也是壳子对PE文件的一种保护啊。。。
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(基础版)
IAT的填充是系统PE加载器完成的,在程序运行之初会一次性全部填充成真是的函数地址,程序用到某个函数的时候,直接去IAT里取函数地址就行,保存函数地址的这个地址是固定不变的。
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(基础版)
你找个PE文件,用LordPE加载,然后点【目录】,其中有一项就是【IAT】,存着IAT的RVA和大小啊,这些信息通过遍历PE文件的目录表都可以遍历得到。
修复IAT的时候,所需要的信息都保存在PE文件的导入表中,从导入表中可以得到函数名,函数模块,然后从函数模块中得到函数地址,导入表中也保存着函数的填充地址(IAT),这样将你得到的函数地址写到IAT就可以了。
参考书籍的话,PE权威指南 里,导入表那一章应该有说明,希望能帮到你。
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(基础版)
首先回答第二个问题:
DWORD dwNumber = (pPEReloc->SizeOfBlock - 8) / 2;//为什么-8还除2????
其中 dwNumber 是这个Reloc区块需要重定位的地址的个数(也就是自己定义的TYPEOFFSET结构体的个数),这个数如何确定,就得分析 IMAGE_BASE_RELOCATION 这个结构体,其结构如图所示:

可见IMAGE_BASE_RELOCATION的前八个字节保存的是 VirtualAddress和SizeOfBlock,所以首先要-8,剩下的都是TypeOffset了,由上面我们自己定义的TYPEOFFSET结构体可知,TypeOffset 是一个数组,数组每项大小为两个字节(16位),它由高 4位和低 12位组成,高 4位代表重定位类型,低 12位是重定位地址,它与VirtualAddress 相加即是指向PE 映像中需要修改的那个代码的地址。
即每个TYPEOFFSET的结构体大小是2个字节。知道总大小,知道单个大小,求数量的话就是总大小除以每个大小,所以是(pPEReloc->SizeOfBlock - 8) / 2
再回答第一个问题:
PTYPEOFFSET pTypeOffset = (PTYPEOFFSET)(pPEReloc + 1);//+1是什么意思啊??
理解了第二问以后,这点也容易理解了,pTypeOffset指向的是TypeOffset数组的首地址,这个首地址相对于这个Reloc区块的偏移是8个字节(前八个字节保存的是VirtualAddress和SizeOfBlock)。(pPEReloc + 1)中的+1其实就是加了8个字节(pPEReloc指向的结构体IMAGE_BASE_RELOCATION的大小就是8个字节)。
这样经过(PTYPEOFFSET)(pPEReloc + 1),+1再强转为PTYPEOFFSET以后就确定TypeOffset数组的首地址了。
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(基础版)
先回答你第一个问题:
if (m_dwImageSize % m_dwMemAlign)
m_dwImageSize = (m_dwImageSize / m_dwMemAlign + 1) * m_dwMemAlign;
其中m_dwImageSize这个变量是PE文件的镜像【总】大小,是从PE文件中获取到的,不是某一个区段的
大小,这个值用LoadPE查看一下,就是在【基本PE头信息】中的第三项【镜像大小】这个值,这个镜像
大小一般都是0x1000对齐的,但由于我在平时测试时发现有些PE文件的镜像大小并不是0x1000对齐,所
以我就在这里校验一下,如果没对齐就对齐一下,方便在后面添加区段。
再回答第二个问题
目标位置的buf是每个区段0x1000对齐以后的,原位置的buf是每个区段默认的0x200对齐的。将后
置往前者拷贝,怎么可能会空间不够呢?
加过无数次一般的简单exe文件都没有任何问题。
你再仔细考虑考虑?
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(扩展版)
我用的是VS2013开发的。
我给出的那个78kb的Shell.dll是我在VS2013下静态编译的( 运行库:多线程 MT )Release版。
你试一下你自己编译exe文件配上压缩包里自带的Shell.dll(78kb)看能不能正常加壳。如果能的话就说明是Shell编译的问题。
确定一下你的dll项目是否是Release(之前为了调试方便,我把shell项目Release的生成目录改成了Debug目录),再确定一下Shell项目是不是按照上图中的方式设置。
在我电脑上下载下来源码然后直接编译出来,加壳是没问题的。
看来VS低版本对高版本的兼容性不太好吧,你也可以看看这个迁移方案,希望能够帮到你:
http://blog.csdn.net/civilman/article/details/40109483
|
能力值:
( LV8,RANK:130 )
|
-
-
|
能力值:
( LV8,RANK:130 )
|
-
-
[原创][开源]用C++实现的壳(扩展版)
 你这个思路实现了吗? 我获取到真正的函数地址以后,不是直接填到对应的IAT地址的啊。。而是直接填到一块new出来的堆空间中的啊,而这个堆空间中填的地址也不是直接就是函数地址,是一段ShellCode的地址,经过一些花指令以后才会call真正的函数地址。
你dump以后成功修复IAT了?  (加壳的时候别忘了选择IAT加密  )
|
能力值:
( LV8,RANK:130 )
|
-
-
[推荐]15PB软件安全更新至2.5版,我们已经离完美越来越近
支持任老师!
培训不易!不能因为只为了就业率而对学员的基础有太高的要求,不然就会让那些基础差的同学失去一次很好的学习机会,所以在15PB的角度看,既要保证没基础的学员的学习质量,又要兼顾基础好的学员能够有所提高,这绝对不是一件容易的事!
就我个人的经历而言,我是个自制力很差的人,大学老师根本不管你,所以基本大学四年就荒废了,来15PB之前我都不会用printf,现在还有一个月就要毕业了,不管我最终能达到什么水平,反正我觉得这半年时间对于我自己而言提高是很大的(估计比我上两次大学学会的知识都多,注意,是学会的。。)
由于每个学员的基础、悟性、学习能力的不同,培训并不能保证每个人都能达到同样的高度,但可以保证对每个人自己而言,绝对是有很大的提高,我觉得这就是培训的价值所在!
任老师加油!
|
能力值:
( LV8,RANK:130 )
|
-
-
|