测试环境:
Windows2000、VC++6.0、ollydbg(原版)
1、代码如下:
#include
#include
int main()
{
LoadLibraryA("user32.dll");
MessageBoxA(0,0,0,0);
char shellcode[1024];
int size=0;
FILE * fp=NULL;
if( !(fp=fopen("D:\\shellcode","rb")) )
{
printf("open file fail!\n");
exit(0);
}
// fscanf函数读取文件全部内容有弊端
fseek(fp, 0, SEEK_END);
size=ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(shellcode,1,size,fp);
fclose(fp);
fp=NULL;
__asm
{
mov eax,fs:[0x30]
int 3 //used to break the process
}
HLOCAL h1,h2,h3,h4,h5,h6;
HANDLE hp;
hp = HeapCreate(0,0x1000,0x10000);
h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
HeapFree(hp,0,h1);
HeapFree(hp,0,h3);
HeapFree(hp,0,h5);
memcpy(h4,shellcode,0xD0); //overflow
h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,0xC0);
return 0;
}
2、shellcode布局如下:
第一行红框8字节代码:DWORD SHOOT除了把shellcode地址值写入指定内存地址中,副作用是这个指定内存地址值会写入shellcode的偏移4字节处,直接使用jmp 06跳过
第二行红框0xB8字节代码:前12个字节是修复peb中RtlEnterCriticalSection( )函数地址,后面的代码是0day中提供的代码,最后4个字节00用来补齐
第三行黄框16字节数据:h5的HEAP_ENTRY结构和双向链表
对应汇编代码如下:
3、在shellcode处下断点,程序退出时会调用peb偏移0x20处的RtlEnterCriticalSection( )函数,这样程序流就转向了我们的代码,再经过漫长的shellcode单步调试,最终会弹出MessageBox对话框。
做这个实验过程中遇到2个问题:
1、在最后一次调用HeapAlloc( )时容易出现异常(实验发现大量申请堆块(代码中申请了6个堆块),不容易出现异常),因为对应的双向链表被认为修改了
2、单纯修复peb中RtlEnterCriticalSection( )函数地址,再直接调用MessageBoxA( )不成功,使用0day中提供的shellcode调用MessageBoxA( )就成功,说明shellcode中的环境修复不仅仅包括RtlEnterCriticalSection( )函数地址,还有其他的环境修复。