2012-02-05 wcdj
1. Stack knowledge required for debugging
2. Memory Corruption caused by illegal array access
Stack knowledge required for debugging
Stack is one of the memory regions in which the program stores data. It features a LIFO (last in first out, last in first out) data structure, that is, the data that is put in the later is first retrieved for backup. The operation to store data in the stack is called push (push), and the data retrieved from the stack is called pop (POP ). Stack is used to save automatically assigned variables dynamically. In addition, the stack is used to pass function parameters and save the return address and return value.
#include <stdio.h> #include <ctype.h> #include <stdlib.h> #define MAX (1UL << 20) typedef unsigned long long u64; typedef unsigned int u32; u32 max_addend = MAX; u64 sum_till_MAX(u32 n) { u64 sum; n++; sum = n; if (n < max_addend) sum += sum_till_MAX(n); return sum; } int main(int argc, char** argv) { u64 sum = 0; if ((argc == 2) && isdigit(*(argv[1]))) max_addend = strtoul(argv[1], NULL, 0); if (max_addend > MAX || max_addend == 0) { fprintf(stderr, "Invalid number is specified\n"); return 1; } sum = sum_till_MAX(0); printf("sum(0..%lu) = %llu\n", max_addend, sum); return 0; }
Calculate the sum from 0 to 10:
$ Gcc-O sum-G sum. c
$./SUM 10
Sum (0 .. 10) = 55
Relationship between function call and stack-Changes of stack before and after function call
On the stack, the parameters passed to the function, the caller's return address, the upper stack frame pointer, and the automatic variables used inside the function are saved in sequence. In addition, the stack is also used to temporarily save registers when processing some functions. Each function has this information, calledStack frame(Stack
Frame ). In this case, you need to set the starting address of the stack frameFrame pointer (FP). In addition,Stack pointer (SP)Always point to the top of the stack.
Invalid array access causes Memory Corruption
One of the Typical Bugs caused by incorrect Array Operations is buffer overflow, that is, writing data out of the allocated memory space. In particular, if such bugs occur in the buffer zone on the stack, they may lead to security vulnerabilities. Therefore, many preventive measures and countermeasures have emerged, for example, you can specify the buffer size to write security functions, source code check tools, and compiler alarms during build. Even so, such bugs happen from time to time.
The following is a simple example:
#include <stdio.h>#include <string.h>char szInfo[] = "Oops! here is a buffer overflow, wcdj";void func() { char buf[5]; strcpy(buf, names);}int main(){ func(); return 0;}
Compile:
Gcc-wall-g-o hack28 hack28.c
Open coredump:
Ulimit-C Unlimited
Run:
Gerryyang @ wcdj :~ /Test/hack>./hack28
Segment error (coredumped)
Gerryyang @ wcdj :~ /Test/hack> ls-RTL
Total 160 K
-RW-r -- 1 gerryyang users 186 hack28.c
-Rwxr-XR-x 1 gerryyang users 7986 hack28
-RW ------- 1 gerryyang users 1474562012-02-05 Core
To debug the program:
Gerryyang @ wcdj :~ /Test/hack> GDB hack28 Core
Gnu gdb 6.6
Copyright (c) 2006 free softwarefoundation, Inc.
GDB is free software, covered by the gnugeneral Public License, and you are
Welcome to change it and/or distributecopies of it under certain conditions.
Type "show copying" to see theconditions.
There is absolutely no warranty forgdb. Type "show warranty" Fordetails.
This GDB was configured as "i586-suse-linux "...
Using host libthread_db library "/lib/libthread_db.so.1 ".
Warning: Can't read pathname for load map: input/output error.
Reading symbols from/lib/libc. so.6...... done.
Loaded symbols for/lib/libc. so.6
Reading symbols from/lib/ld-linux.so.2... done.
Loaded symbols for/lib/ld-linux.so.2
Core was generated by './hack28 '.
Program terminated with signal 11, segmentation fault.
#0 0x73692065 in ?? ()
(GDB) BT
#0 0x73692065 in ?? ()
#1 0x62206120 in ?? ()
#2 0x65666675 in ?? ()
#3 0x766f2072 in ?? ()
#4 0x6c667265 in ?? ()
#5 0x202c776f in ?? ()
#6 0x6a646377 in ?? ()
#7 0xbfb48600 in ?? ()
#8 0xb7e5a89c in _ libc_start_main () from/lib/libc. so.6
Backtrace stopped: Previous frame inner tothis frame (upt stack ?)
(GDB) x/I 0x73692065
0x73692065: cannot access memory at address 0x73692065
(GDB) x/I 0x62206120
0x62206120: cannot access memory at address0x62206120
(GDB)
Backtrace cannot be correctly displayed. In this case, backtrace is unreliable. Because the content displayed by backtrace is probably not actually tracked. That is, the Code suddenly jumps to or calls the wrong address 0x73692065, resulting in segmentation fault.
Note: It is difficult to place programs and shared memory on the address displayed on Stack frames #0 and #1. In most Linux releases of the i386 architecture, the program is located near the address 0x08000000, and the shared library is located after the address 0xb0000000. Therefore, remember what address will be located in the program and shared library under standard conditions in the debugging object environment and it will be very convenient to read backtrace.
(GDB) x/30C $ sp
0xbfb48660: 32 ''97 'a '32' '98 'B' 117 'u'000000' f'000000' f'000000' e'
0xbfb48668: 114 'r'32' '000000' o '000000' v '000000' e '000000' r'000000' f'000000' l'
0xbfb48670: 111 'O' 119 'w'44', '32' '000000' w'99 'C' 119 'D' 100 'J'
0xbfb48678: 0' \ 0'-122 '\ 206'-76'''-65 '0000'-100 '\ 234'-88 'l'
Sp-15 (GDB) x/30C $
0xbfb48651: 31 '\ 037'-8 'ø '79' o '000000' o '000000' P '000000' s '33 '! '32''
0xbfb48659: 104 'h'000000' e '000000'101 'E' 32 ''105 'I '123'32''
0xbfb48661: 97 'a '32' 98 'B' 117 'u'000000' f'000000' f'000000' e '000000' R'
0xbfb48669: 32 '000000' o '000000' v '000000' e '000000' R '000000' f'
(GDB) P (char *) $ sp-15
$1 = 0xbfb48651 "\ 037 ø oops! Here is abuffer overflow, wcdj"
Sp-15 (GDB) x/30 W $
0xbfb48651: 0x6f4ff81f 0x20217370 0x65726568 0x20736920
0xbfb48661: 0x75622061 0x72656666 0x65766f20 0x6f6c6672
0xbfb48671: 0x77202c77 0x006a6463 0x9cbfb1_0x01b7e5a8
0xbfb48681: 0x04000000 0x0cbfb487 0x3dbfb487 0x00b7f9cc
0xbfb48691: 0x90000000 0x01b7f8f6 0x01000000 0xf4000000
0xbfb486a1: 0xc0b7f81f 0x00b7fabc 0xd8000000 0x80bfb0000
0xbfb486b1: 0x6140be86 0x0048efa8 0x00000000 0x00000000
0xbfb486c1: 0x70000000 0xcdb7fa20
Find the place where the data 0x700002065 is incorrectly written. It is important to check whether the data is a part of the string, because one typical case of mistakenly writing data into the address is string replication. It is difficult to predict the length of the input string. If the buffer is too small and the check for the length of the input string is incomplete, this situation may occur. Considering that the i386 architecture is littleendian, it is suspected that part of the string "... EIS..." has been written. This assumption is then verified. First, the stack pointer points to almost all strings before and after the space. Therefore, writing this string to the wrong position on the stack is highly likely, and the Code shows that the Buf is only 5 bytes long, the copied string exceeds this length, leading to buffer overflow.
Through the above analysis, the cause of the error is that the space written by strcpy () to the string is originally used to save the space that returns the main () address. Therefore, after func () ends, main () is returned () when the "... E is... "The corresponding 0x700002065 value is used as the return address of the function, resulting in segmentation fault.
In this example, the address is a part of the string, which is easier to judge, but it is more difficult to investigate if the value is incorrectly written. Even so, if that value often appears in the program, you can narrow down the scope of the investigation to the part where the value is used.
You can also use the objdump tool.
Gerryyang @ wcdj :~ /Test/hack> objdump-shack28
Hack28: File Format elf32-i386
. Interp content:
8048154 2f6c6962 2f6c642d 6c696e75782e736f/lib/ld-linux.so
8048164 2e3200
......
Contents of. Got. PLT section:
8049644 78950408 00000000 X ...............
8049654 16830408 26830408 ....&...
. Data section content:
8049660 00000000 00000000 70950408 00000000 .......
8049670 00000000 00000000 0000000000000000 ................
8049680 4f6f7073 21206865 72652069 73206120 oops! Here is
8049690 62756666 6572206f 766521366c6f772c buffer overflow,
80496a0 20776364 6a000000 wcdj...
Content of the. comment section:
......
Summary
The process of determining whether the memory content is damaged can be performed according to certain steps, but finding the cause of the damage must rely on a certain sense and experience.
Reference: Debug hacks