【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

时间:2022-07-16 21:46:35

作者

作者:admin-神风

本文章是为了写出来让人们交流学习的~~末尾我会放上我写这篇文章时所遇到的问题。希望看完本帖的人可以在末尾评论留言自己的问题和解决的答案和思路~

黑客是一种分享的精神!但现在看来却是在慢慢消失,所以--我希望看完本帖的人们能传递下去!

由于技术问题 本帖有错误的地方望各位大牛斧正!

 

之前讲了栈溢出的基础部分  以及怎么找JMP ESP

由于上次实验是在WIN7环境下实验的  但win7以上的版本已经有DEP保护 每次JMP ESP的地址是不确定的(可以用rop绕过DEP)

 

正文

本次实验用弹出计算器(calc.exe)来编写

代码如下

#include <stdio.h>
#include <windows.h>
int main()
{
    
    LoadLibraryA("kernel32.dll");
    WinExec("calc.exe", SW_SHOW);

    return 0;
}

我们直接汇编看看程序是怎么运作的

载入ollydbg

由于程序一开始并不是我们的入口地址

这里我用IDA来查找入口地址

载入点击搜索 搜索LoadLibraryA加载时的地址

如图

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

再往上翻一点 可以看到程序的入口地址是00401010

再到OD里面右键-转到-表达式

直接输入00401010

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

找到程序入口了  在这里按F2下一个断点 F9过去

F8单步步过

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

在这里可以看到  把636C6163的值赋值给了栈中的0012FF3C的地址

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

那么看看636C6163是什么东东呢?

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

原来是把要执行的内容压入栈中了 

继续步过  发现后面调用dll和WinExec函数

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

可以看到依次把LoadLibraryA调用的dll地址和WinExec函数地址压入栈中  为了以后的方便调用

我们利用工具先看看地址是多少

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

然后步过到调用WinExec函数的地址

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

可以看到请求了775BEDB2这个函数的地址

最后弹出计算器

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

初步shellcode编写

之前说过了 win7系统重启后 函数的地址是会变化的

这里放个我下午的截图

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

明显和上午不一样的地址了

 

之前讲到了程序运行的原理

现在就开始针对程序的整个过程来编写自己的shellcode

我们总结下上述程序的大致运行过程

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

程序要用LoadLibraryA加载一个kernel32.dll

①获取WinExec函数的地址

②调用之前已经压入栈中的地址0042201C

③找到对应地址的内容并弹回WinExec函数的地方

④弹出计算器

下面将开始编写我们的shellcode

 

在C语言中  用汇编内嵌写入代码需要用到_asm{}写入

我们可以知道  程序首先将我们的calc.exe的地址压栈了

于是我们通过一个指针来帮我们压calc.exe到栈

#include <stdio.h>
#include <windows.h>
int main()
{
    char str[]="calc.exe";
    char* p = str;

    LoadLibraryA("kernel32.dll");//x76ff0000
    WinExec("calc.exe", SW_SHOW);
    
    _asm
    {
      
        mov eax,p;
        push eax;
        
    }
    
    return 0;
}

 

 

mov找到p指针的地址  把地址赋值给eax(此时p指向的地址就是0042201C)

随后push压栈

好,下面就是用WinExec函数去调用我们已经压好的内容了

mov eax,0x7707edb2;  //WinExec的地址
call eax

 

这样  我们就做到了要WinExec函数去调用0042201C地址的内容

最后写成如下代码:

#include <stdio.h>
#include <windows.h>
int main()
{
    char str[]="calc.exe";
    char* p = str;

    LoadLibraryA("kernel32.dll");//x76ff0000
    //WinExec("calc.exe", SW_SHOW);

    _asm
    {
        push 0;

        mov eax,p
        push eax
        mov eax,0x7707edb2;  //WinExec的地址
        call eax    
    }
    return 0;
}

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

也许细心的人就会发现~  我的汇编代码中为什么多了个push 0?????

这里我用OD深入分析

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

因为我们之前已经把p地址的内容压入栈中去了

所以此时call就是调用0012FF3C的栈空间里的数据了

而不是本身程序中的数据哦~

过去看看

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

因为我们已经push 0

所以0012FF44的地址上就是CCCCCC00咯  这样做的好处是 防止程序继续往下走,00的作用就是截断

如果程序继续往下走  那么你的程序迟早会崩溃的 因为下面有什么  谁都不知道~~

【原创】后续浅谈栈溢出之shellcode编写的艺术(一)

虽然成功执行了 但是会出现程序崩溃(读者们可以自行测试)

现在已经写好了汇编代码

可... 有个大问题 这里我们是用的p指针压栈的,那没p指针我们的shellcode就没卵用了。。。

那么 我们应该尽可能的把要执行的东西全部写到我们的汇编代码中 这样我们的shellcode才独立 可以在不同的软件中执行

 具体写法将会在下一章中讲解

本章已结束 未完待续...