Some 64-bit glibc payloads fail to call system functions
Original link
When I was working on the question, I found out that some new 64-bit glibc will crash directly when calling the system function after controlling the program flow. After debugging, I finally found the problem.
Download the files used in the experiment, Baidu network disk: https://pan.baidu.com/s/1mEcCIzeYtDIo-xmHsM8AFA (extraction code: ycyx
).
question
When doing 64-bit pwn questions, especially stack overflow, after controlling the program flow, I thought that the shell could be obtained by directly calling the system function, but what we often see is a crash:
Thread 2.1 "speedrun-002" received signal SIGSEGV, Segmentation fault.
[Switching to process 25578]
0x00007f134a9fc2f6 in do_system (line=0x7f134ab60e9a "/bin/sh") at ../sysdeps/posix/system.c:125
125 ../sysdeps/posix/system.c: No such file or directory.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────
RAX 0x7f134ab60e97 ◂— sub eax, 0x622f0063 /* '-c' */
RBX 0x0
RCX 0x7f134ab60e9f ◂— jae 0x7f134ab60f09 /* 'sh' */
RDX 0x0
RDI 0x2
RSI 0x7f134ad9a6a0 (intr) ◂— 0x0
R8 0x7f134ad9a600 (quit) ◂— 0x0
R9 0x10
R10 0x8
R11 0x246
R12 0x7f134ab60e9a ◂— 0x68732f6e69622f /* '/bin/sh' */
R13 0x7ffe3e3eb140 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x601ce1 ◂— 0x0
RSP 0x601c81 ◂— 0x0
RIP 0x7f134a9fc2f6 (do_system+1094) ◂— movaps xmmword ptr [rsp + 0x40], xmm0
──────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────
► 0x7f134a9fc2f6 <do_system+1094> movaps xmmword ptr [rsp + 0x40], xmm0
0x7f134a9fc2fb <do_system+1099> call sigaction <0x7f134a9ec110>
0x7f134a9fc300 <do_system+1104> lea rsi, [rip + 0x39e2f9] <0x7f134ad9a600>
0x7f134a9fc307 <do_system+1111> xor edx, edx
0x7f134a9fc309 <do_system+1113> mov edi, 3
0x7f134a9fc30e <do_system+1118> call sigaction <0x7f134a9ec110>
0x7f134a9fc313 <do_system+1123> xor edx, edx
0x7f134a9fc315 <do_system+1125> mov rsi, rbp
0x7f134a9fc318 <do_system+1128> mov edi, 2
0x7f134a9fc31d <do_system+1133> call sigprocmask <0x7f134a9ec140>
0x7f134a9fc322 <do_system+1138> mov rax, qword ptr [rip + 0x39bb7f]
STACK ]───────────────────────────────────────────────────
00:0000│ rsp 0x601c81 ◂— 0x0
01:0008│ 0x601c89 —▸ 0x7f134ab60e97 ◂— sub eax, 0x622f0063 /* ‘-c’ */
02:0010│ 0x601c91 ◂— 0x0
↓
04:0020│ 0x601ca1 —▸ 0x7f134a9fc360 (cancel_handler) ◂— push rbx
05:0028│ 0x601ca9 —▸ 0x601c9d ◂— 0x4a9fc36000000000
06:0030│ 0x601cb1 ◂— 0x0
↓
BACKTRACE ]─────────────────────────────────────────────────
f 0 7f134a9fc2f6 do_system+1094
f 1 a
f 2 0
Program received signal SIGSEGV (fault address 0x0)
The program crashed directly.
reason
The main reason is that the value required by 0x4F2F6
the movaps [rsp+198h+var_158], xmm0
instruction rsp+198h+var_158
is aligned 16byte
(0x10), otherwise it will directly trigger an interrupt and crash.
.text:000000000004F2F1 movhps xmm0, [rsp+198h+var_190]
.text:000000000004F2F6 movaps [rsp+198h+var_158], xmm0 ; here
.text:000000000004F2FB call sigaction
demo
Here I use a simple program to demonstrate the problem.
shell.c
// compiled: gcc -g -no-pie -Og shell.c -o shell
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
system("/bin/sh");
return 0;
}
After the program is compiled, it can run normally, but what we want is to make the program not run normally.
Next, we will directly .text:000000000004F2F6 movaps [rsp+198h+var_158], xmm0 ; here
set a breakpoint here, that is do_system+1094
, and then run here.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────
RAX 0x7ffff7b97e97 ◂— sub eax, 0x622f0063 /* '-c' */
RBX 0x0
RCX 0x7ffff7b97e9f ◂— jae 0x7ffff7b97f09 /* 'sh' */
RDX 0x0
RDI 0x2
RSI 0x7ffff7dd16a0 (intr) ◂— 0x0
R8 0x7ffff7dd1600 (quit) ◂— 0x0
R9 0x7ffff7dd0d80 (initial) ◂— 0x0
R10 0x8
R11 0x246
R12 0x400594 ◂— 0x68732f6e69622f /* '/bin/sh' */
R13 0x7fffffffdc60 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x7fffffffda40 ◂— 0x0
RSP 0x7fffffffd9e0 ◂— 0x0
RIP 0x7ffff7a332f6 (do_system+1094) ◂— movaps xmmword ptr [rsp + 0x40], xmm0
──────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────
► 0x7ffff7a332f6 <do_system+1094> movaps xmmword ptr [rsp + 0x40], xmm0
0x7ffff7a332fb <do_system+1099> call sigaction <0x7ffff7a23110>
0x7ffff7a33300 <do_system+1104> lea rsi, [rip + 0x39e2f9] <0x7ffff7dd1600>
0x7ffff7a33307 <do_system+1111> xor edx, edx
0x7ffff7a33309 <do_system+1113> mov edi, 3
0x7ffff7a3330e <do_system+1118> call sigaction <0x7ffff7a23110>
0x7ffff7a33313 <do_system+1123> xor edx, edx
0x7ffff7a33315 <do_system+1125> mov rsi, rbp
0x7ffff7a33318 <do_system+1128> mov edi, 2
0x7ffff7a3331d <do_system+1133> call sigprocmask <0x7ffff7a23140>
0x7ffff7a33322 <do_system+1138> mov rax, qword ptr [rip + 0x39bb7f]
STACK ]───────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffd9e0 ◂— 0x0
01:0008│ 0x7fffffffd9e8 —▸ 0x7ffff7b97e97 ◂— sub eax, 0x622f0063 /* ‘-c’ /
02:0010│ 0x7fffffffd9f0 ◂— 0x0
↓
04:0020│ 0x7fffffffda00 —▸ 0x7ffff7a33360 (cancel_handler) ◂— push rbx
05:0028│ 0x7fffffffda08 —▸ 0x7fffffffd9fc ◂— 0xf7a3336000000000
06:0030│ 0x7fffffffda10 —▸ 0x7ffff7ffe738 —▸ 0x7ffff7ffe710 —▸ 0x7ffff7ffa000 ◂— jg 0x7ffff7ffa047
07:0038│ 0x7fffffffda18 ◂— 0x0
BACKTRACE ]─────────────────────────────────────────────────
f 0 7ffff7a332f6 do_system+1094
f 1 7ffff7a3344a system+10
f 2 4004f7 main+16
f 3 7ffff7a05b97 __libc_start_main+231
Breakpoint (0x7ffff7a32eb0+1094)
Then look at rsp + 0x40
the value.
pwndbg> p/x $rsp+0x40
$1 = 0x7fffffffda20
It can be seen that the value at this time is aligned, so it can run normally. Let's try to add rsp
1 to see if it will crash.
pwndbg> set $rsp=$rsp+1
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────
RAX 0x7ffff7b97e97 ◂— sub eax, 0x622f0063 /* '-c' */
RBX 0x0
RCX 0x7ffff7b97e9f ◂— jae 0x7ffff7b97f09 /* 'sh' */
RDX 0x0
RDI 0x2
RSI 0x7ffff7dd16a0 (intr) ◂— 0x0
R8 0x7ffff7dd1600 (quit) ◂— 0x0
R9 0x7ffff7dd0d80 (initial) ◂— 0x0
R10 0x8
R11 0x246
R12 0x400594 ◂— 0x68732f6e69622f /* '/bin/sh' */
R13 0x7fffffffdc60 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x7fffffffda40 ◂— 0x0
*RSP 0x7fffffffd9e1 ◂— 0x9700000000000000
RIP 0x7ffff7a332f6 (do_system+1094) ◂— movaps xmmword ptr [rsp + 0x40], xmm0
──────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────
► 0x7ffff7a332f6 <do_system+1094> movaps xmmword ptr [rsp + 0x40], xmm0
0x7ffff7a332fb <do_system+1099> call sigaction <0x7ffff7a23110>
0x7ffff7a33300 <do_system+1104> lea rsi, [rip + 0x39e2f9] <0x7ffff7dd1600>
0x7ffff7a33307 <do_system+1111> xor edx, edx
0x7ffff7a33309 <do_system+1113> mov edi, 3
0x7ffff7a3330e <do_system+1118> call sigaction <0x7ffff7a23110>
0x7ffff7a33313 <do_system+1123> xor edx, edx
0x7ffff7a33315 <do_system+1125> mov rsi, rbp
0x7ffff7a33318 <do_system+1128> mov edi, 2
0x7ffff7a3331d <do_system+1133> call sigprocmask <0x7ffff7a23140>
0x7ffff7a33322 <do_system+1138> mov rax, qword ptr [rip + 0x39bb7f]
STACK ]───────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffd9e1 ◂— 0x9700000000000000
01:0008│ 0x7fffffffd9e9 ◂— 0x7ffff7b97e
02:0010│ 0x7fffffffd9f1 ◂— 0x0
03:0018│ 0x7fffffffd9f9 ◂— 0x6000000000000000
04:0020│ 0x7fffffffda01 ◂— 0xfc00007ffff7a333
05:0028│ 0x7fffffffda09 ◂— 0x3800007fffffffd9
06:0030│ 0x7fffffffda11 ◂— 0x7ffff7ffe7
07:0038│ 0x7fffffffda19 ◂— 0x100000000000000
BACKTRACE ]─────────────────────────────────────────────────
f 0 7ffff7a332f6 do_system+1094
f 1 4004
f 2 9700000000000000
f 3 100007ffff7a05b
f 4 6800000000000000
f 5 7fffffffdc
f 6 e700000001000080
f 7 4004
f 8 a400000000000000
f 9 6b6cdf11464cf7
f 10 6000000000004004
Breakpoint *(0x7ffff7a32eb0+1094)
Continue to view rsp + 0x40
the values.
pwndbg> p/x $rsp+0x40
$2 = 0x7fffffffda21
You can see that it is not aligned at this time, so continue to run.
pwndbg> c
Continuing.
Thread 2.1 “shell” received signal SIGSEGV, Segmentation fault.
0x00007ffff7a332f6 in do_system (line=0x400594 “/bin/sh”) at …/sysdeps/posix/system.c:125
125 in …/sysdeps/posix/system.c
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
REGISTERS ]─────────────────────────────────────────────────
RAX 0x7ffff7b97e97 ◂— sub eax, 0x622f0063 /* ‘-c’ /
RBX 0x0
RCX 0x7ffff7b97e9f ◂— jae 0x7ffff7b97f09 / ‘sh’ /
RDX 0x0
RDI 0x2
RSI 0x7ffff7dd16a0 (intr) ◂— 0x0
R8 0x7ffff7dd1600 (quit) ◂— 0x0
R9 0x7ffff7dd0d80 (initial) ◂— 0x0
R10 0x8
R11 0x246
R12 0x400594 ◂— 0x68732f6e69622f / ‘/bin/sh’ */
R13 0x7fffffffdc60 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x7fffffffda40 ◂— 0x0
RSP 0x7fffffffd9e1 ◂— 0x9700000000000000
RIP 0x7ffff7a332f6 (do_system+1094) ◂— movaps xmmword ptr [rsp + 0x40], xmm0
DISASM ]───────────────────────────────────────────────────
0x7ffff7a332f6 <do_system+1094> movaps xmmword ptr [rsp + 0x40], xmm0
0x7ffff7a332fb <do_system+1099> call sigaction <0x7ffff7a23110>
0x7ffff7a33300 <do_system+1104> lea rsi, [rip + 0x39e2f9] <0x7ffff7dd1600>
0x7ffff7a33307 <do_system+1111> xor edx, edx
0x7ffff7a33309 <do_system+1113> mov edi, 3
0x7ffff7a3330e <do_system+1118> call sigaction <0x7ffff7a23110>
0x7ffff7a33313 <do_system+1123> xor edx, edx
0x7ffff7a33315 <do_system+1125> mov rsi, rbp
0x7ffff7a33318 <do_system+1128> mov edi, 2
0x7ffff7a3331d <do_system+1133> call sigprocmask <0x7ffff7a23140>
0x7ffff7a33322 <do_system+1138> mov rax, qword ptr [rip + 0x39bb7f]
STACK ]───────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffd9e1 ◂— 0x9700000000000000
01:0008│ 0x7fffffffd9e9 ◂— 0x7ffff7b97e
02:0010│ 0x7fffffffd9f1 ◂— 0x0
03:0018│ 0x7fffffffd9f9 ◂— 0x6000000000000000
04:0020│ 0x7fffffffda01 ◂— 0xfc00007ffff7a333
05:0028│ 0x7fffffffda09 ◂— 0x3800007fffffffd9
06:0030│ 0x7fffffffda11 ◂— 0x7ffff7ffe7
07:0038│ 0x7fffffffda19 ◂— 0x100000000000000
BACKTRACE ]─────────────────────────────────────────────────
f 0 7ffff7a332f6 do_system+1094
f 1 4004
f 2 9700000000000000
f 3 100007ffff7a05b
f 4 6800000000000000
f 5 7fffffffdc
f 6 e700000001000080
f 7 4004
f 8 a400000000000000
f 9 6b6cdf11464cf7
f 10 6000000000004004
Program received signal SIGSEGV (fault address 0x0)
As you can see from the above, the program crashes directly.
Solution
The core idea is to change the address of the stack.
- Change payload length
- stack transfer
Change payload length
Directly change the length of our payload. When the stack overflows, the address of the stack will naturally be different. Then, +1
if the address of the stack does not work, it will continue to increase. If it is changed 16 times at most, the stack will definitely be aligned.
stack transfer
When the payload has a length limit, we can try to transfer the stack to change the stack address. If there is no alignment, continue to change the stack address +1
until the stack is aligned.
call execve
The execve function is used to replace the system function, and this requirement is even higher, because it needs three parameters to be called normally. That is to say, we need to construct rdi
, rsi
, rdx
these three parameters.
int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
Summarize
If you encounter problems, start debugging more.