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

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

2020-4-12 16:01
11357

背景

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

功能

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

DWORD WINAPI EasyShellCodeMain(LPVOID pParam)
{
	char out[] = { 'a', 'b' , 'c', '\0' };
	API(KERNEL32, OutputDebugStringA)(out);

	return 0;
}

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

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

#include "Code.h"

typedef DWORD (WINAPI* TStartFun)(LPVOID lpParam);
int main()
{
	PBYTE lpBuffer = (PBYTE)VirtualAlloc(0, sizeof(g_ShellCode),  MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	CopyMemory(lpBuffer, g_ShellCode, sizeof(g_ShellCode));
	return ((TStartFun)lpBuffer)(0);
}


原理

首先是API这个宏:

#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是最后一个(一般只要保证文件名是大写字母开头就行)。



支持X86和X64。


代码

https://gitee.com/on_my_note/EasyShellCode

PS

代码开放给大家学习,

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-4-12 16:02 被独—行编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (16)
雪    币: 3017
活跃值: (1149)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
zhouws 2 2020-4-12 16:23
2
0
这菜鸟有点意思
雪    币: 504
活跃值: (3061)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wem 2020-4-12 21:11
3
0
马克
雪    币: 4709
活跃值: (1549)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
如斯咩咩咩 2020-4-12 21:58
4
0
mark
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
人在塔在 2020-4-13 11:27
5
0
makr
雪    币: 1042
活跃值: (455)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Rookietp 2020-4-13 12:41
6
0
学习C++新写法
最后于 2020-4-13 12:42 被Rookietp编辑 ,原因:
雪    币: 5893
活跃值: (4477)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
淡然他徒弟 1 2020-4-14 04:16
7
0
mark
雪    币: 1655
活跃值: (1546)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
自由狼 2020-10-30 14:56
8
0
好像没什么效果,可能我看不懂
雪    币: 1655
活跃值: (1546)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
自由狼 2020-11-3 16:57
9
0
不好意思 有效果,是我忽略了一个调用,没注意,非常棒的源码,感谢分享
雪    币: 222
活跃值: (260)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
fgfxf 2023-8-17 12:07
10
0
gitee打不开了,能再分享一下吗?求求了
雪    币: 222
活跃值: (260)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
fgfxf 2023-8-17 12:21
11
0
返回值如何处理呢?
雪    币: 1367
活跃值: (92)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
独—行 2024-3-14 09:59
12
0
fgfxf gitee打不开了,能再分享一下吗?求求了

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

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


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

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

雪    币: 94
活跃值: (400)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dico 2024-4-18 18:31
15
0

学习

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

GOOD

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