首页
社区
课程
招聘
[原创]超简单的C++编写Windows平台ShellCode的框架
发表于: 2020-4-12 16:01 12860

[原创]超简单的C++编写Windows平台ShellCode的框架

2020-4-12 16:01
12860

功能

可以向写普通C++代码一样写ShellCode,写完直接编译即可以生成相应的代码,直接引用即可。( 字符串还是要拆开写的)

所有的API都可以像上面这样直接调用,程序会自动生成相应的库的代码

编译后,程序会自动生成Code.h头文件,直接引用即可.

首先是API这个宏:



支持X86和X64。


来看雪很长时间了,在这里学到了不少东西,本人菜鸡一只,一直在潜水。
周末整理了一下笔记,整理出这个ShellCode编写框架,取名EasyShellCode,不敢独享,分享给大家,希望有用。

#define API(DLLNAME, FUNNAME) ((decltype(&FUNNAME))WinApi::ForceCalc<WinApi::ELFNoCaseHash(#DLLNAME ".dll"), WinApi::CalcHash(#FUNNAME)>())

这里用到了 C++11的decltype(下面还会用到C++14的constexpr,这也是要求高版本编译器的原因)如果不用高版本编译器,函数类型的声明就要自己写.
整体思想就是通过计算字符串的hash值去找到对应的模块.其中WinApi::ForceCalc是一个模板函数,定义如下:
template<DWORD dwDllName, DWORD dwFunName>
__forceinline PVOID ForceCalc()
{
	return GetApiAddr(dwDllName, dwFunName);
}
这个函数看起来没什么用, 但是把它去掉就能发现问题了. 为什么呢? 得说完hash计算方法后再说.

下面继续看 ELFNoCaseHash 函数,因为Dll的名字是不区分大小写的,所以这里用了一个不区分大小写的hash生成函数
constexpr UINT ELFNoCaseHash(LPCSTR str, UINT nLen = UINT_MAX)
{
	if (nullptr == str) {
		return -1;
	}
	UINT hash = 0;
	UINT test = 0;
	while (*str && nLen) {
		hash = (hash << 4) + MiniToUpper((*str++));
		if ((test = hash & 0xF0000000) != 0) {
			hash = ((hash ^ (test >> 24)) & (~test));
		}
		nLen--;
	}

	return hash;
}
精髓就是constexpr, 这个关键字会让编译器尽可能在编译器计算值,因为字符串是个常量,所以在编译器计算hash是可能的,这也就导致了编译到最后代码中的不是一个字符串常量,而是一个hash整数.
再来说为什么要有WinApi::ForceCalc,简单来说就是  constexpr编译器不保证真的在编译器计算出值(有的是因为根本计算不出来值,有的是因为它偷懒了)。怎么办呢?  就是通过这个函数模板让它强制计算(它不计算就不知道怎么生成模板函数),也就是名字的由来。

剩下的技巧就没什么了,就是一个根据hash值找对应函数的方法了.  主要靠 GetApiAddr函数实现.
这个函数先去PEB中查找已经加载的模块(请查看GetModuleHandleFromPeb 函数实现), 如果找到了,那么直接去模块中找函数地址. 反之如果没找到,那么就去加载它(请查看 GetModuleHandleFromDllNum 函数实现).具体去看下代码吧,就没什么技巧了.

项目支持多文件,需要添加文件.
如之前所说,Main.cpp中的 EasyShellCodeMain就是ShellCode的入口函数,如果用到其他文件,直接添加即可.
但要保证AAAAAStart.cpp是第一个,ZZZZZEnd.cpp是最后一个(一般只要保证文件名是大写字母开头就行)。
template<DWORD dwDllName, DWORD dwFunName>
__forceinline PVOID ForceCalc()
{
	return GetApiAddr(dwDllName, dwFunName);
}
这个函数看起来没什么用, 但是把它去掉就能发现问题了. 为什么呢? 得说完hash计算方法后再说.

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-4-12 16:02 被独—行编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (16)
雪    币: 3116
活跃值: (1269)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
这菜鸟有点意思
2020-4-12 16:23
0
雪    币: 515
活跃值: (3272)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wem
3
马克
2020-4-12 21:11
0
雪    币: 4709
活跃值: (1575)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
4
mark
2020-4-12 21:58
0
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
makr
2020-4-13 11:27
0
雪    币: 1042
活跃值: (500)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习C++新写法
最后于 2020-4-13 12:42 被Rookietp编辑 ,原因:
2020-4-13 12:41
0
雪    币: 6166
活跃值: (4937)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
7
mark
2020-4-14 04:16
0
雪    币: 1853
活跃值: (1923)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
好像没什么效果,可能我看不懂
2020-10-30 14:56
0
雪    币: 1853
活跃值: (1923)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不好意思 有效果,是我忽略了一个调用,没注意,非常棒的源码,感谢分享
2020-11-3 16:57
0
雪    币: 222
活跃值: (315)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
gitee打不开了,能再分享一下吗?求求了
2023-8-17 12:07
0
雪    币: 222
活跃值: (315)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
返回值如何处理呢?
2023-8-17 12:21
0
雪    币: 1367
活跃值: (97)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
fgfxf gitee打不开了,能再分享一下吗?求求了

抱歉,抱歉,好久没登陆了,半年后的今天才看到。Gitee改了,所以不能公开仓库了。代码我放在附件里了。

上传的附件:
2024-3-14 09:59
0
雪    币: 1367
活跃值: (97)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
fgfxf 返回值如何处理呢?
直接定义了函数指针类型,直接像调用函数一样调用Shellcode,然后返回值给变量赋值就可以了。
2024-3-14 10:01
0
雪    币: 30050
活跃值: (2447)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14


没必要什么文件名称顺序的。。。

在abc.txt里面按顺序写上函数名称即可,编译出来的就是顺序排列,并且是紧密排列。

2024-3-14 14:48
1
雪    币: 94
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15

学习

最后于 2024-4-18 21:34 被dico编辑 ,原因:
2024-4-18 18:31
0
雪    币: 94
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
自由狼 不好意思 有效果,是我忽略了一个调用,没注意,非常棒的源码,感谢分享

GOOD

最后于 2024-4-18 19:38 被dico编辑 ,原因:
2024-4-18 18:49
0
游客
登录 | 注册 方可回帖
返回
//