Control: tags -1 + upstream patch

Dear Maintainer,
I tried to have a look into this issue and guess I found something.

It looks like the application is exhausting its stack by
allocation an integer array with maxpid elements.
At least in my test VM this leads to 16 MB array size,
while stack has just a size of 8 MB.

Attached patch allocates two such arrays from the heap.
With this "unhide brute" could finish without crash.

Another workaround would be to increase stacksize
by "ulimit -s 40960" before running unhide.

Kind regards,
Bernhard



dmesg by submitter:
Nov 30 01:39:48 heisenberg kernel: unhide[208429]: segfault at 7ffd06cfec58 ip 
000055c15aa077d3 sp 00007ffd06cfec60 error 6 in unhide-linux[55c15aa07000+6000]
Nov 30 01:39:48 heisenberg kernel: Code: 00 48 89 45 c8 31 c0 48 63 05 5d 98 00 
00 48 8d 04 85 0f 00 00 00 48 83 e0 f0 48 29 c4 48 89 65 98 48 29 c4 31 c0 48 
89 65 90 <e8> d8 3e 00 00 31 c0 66 0f 1f 44 00 00 48 8b 4d 98 48 8b 55 90 c7



/*
 * Page fault error code bits:
 *
 *   bit 0 ==    0: no page found       1: protection fault
 *   bit 1 ==    0: read access         1: write access
 *   bit 2 ==    0: kernel-mode access  1: user-mode access
 *   bit 3 ==                           1: use of reserved bit detected
 *   bit 4 ==                           1: fault was an instruction fetch
 *   bit 5 ==                           1: protection keys block access
 */
enum x86_pf_error_code {

        PF_PROT         =               1 << 0,
        PF_WRITE        =               1 << 1,
        PF_USER         =               1 << 2,
        PF_RSVD         =               1 << 3,
        PF_INSTR        =               1 << 4,
        PF_PK           =               1 << 5,
};

arch/x86/mm/fault.c:
    printk("%s%s[%d]: segfault at %lx ip %px sp %px error %lx",


"error 6" == 0x6 == 0b110

bit 0 ==         0: no page found
bit 1 ==         1: write access
bit 2 ==         1: user-mode access
bit 3 ==         0: 
bit 4 ==         0: 
bit 5 ==         0: 





# Bullseye/testing amd64 qemu VM 2019-12-03

apt update
apt dist-upgrade

apt install systemd-coredump mc devscripts dpkg-dev gdb unhide unhide-dbgsym


mkdir /home/benutzer/source/unhide/orig -p
cd    /home/benutzer/source/unhide/orig
apt source unhide
cd



gdb -q --args unhide

set width 0
set pagination off
directory /home/benutzer/source/unhide/orig/unhide-20130526
b main
run
dele 1

info target

find /b 0x00005555555563e0, 0x000055555555b001, 0x00, 0x48, 0x89, 0x45, 0xc8, 
0x31, 0xc0, 0x48, 0x63, 0x05, 0x5d, 0x98, 0x00, 0x00, 0x48, 0x8d, 0x04, 0x85, 
0x0f, 0x00, 0x00, 0x00, 0x48, 0x83, 0xe0, 0xf0, 0x48, 0x29, 0xc4, 0x48, 0x89, 
0x65, 0x98, 0x48, 0x29, 0xc4, 0x31, 0xc0, 0x48, 0x89, 0x65, 0x90, 0xe8, 0xd8, 
0x3e, 0x00, 0x00, 0x31, 0xc0, 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, 0x48, 0x8b, 
0x4d, 0x98, 0x48, 0x8b, 0x55, 0x90, 0xc7



root@debian:~# gdb -q --args unhide
Reading symbols from unhide...
Reading symbols from 
/usr/lib/debug/.build-id/41/d7d39535f738606ad3acf0611a8397925762b3.debug...
(gdb) set width 0
(gdb) set pagination off
(gdb) directory /home/benutzer/source/unhide/orig/unhide-20130526
Source directories searched: 
/home/benutzer/source/unhide/orig/unhide-20130526:$cdir:$cwd
(gdb) b main
Breakpoint 1 at 0x23e0: file /usr/include/x86_64-linux-gnu/bits/stdio2.h, line 
107.
(gdb) run
Starting program: /usr/sbin/unhide 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=1, argv=0x7fffffffed18) at 
/usr/include/x86_64-linux-gnu/bits/stdio2.h:107
warning: Source file is more recent than executable.
107       return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack 
());
(gdb) dele 1
(gdb) info target
Symbols from "/usr/sbin/unhide-linux".
Native process:
        Using the running image of child Thread 0x7ffff7de5740 (LWP 13520).
        While running this, GDB does not access memory from...
Local exec file:
        `/usr/sbin/unhide-linux', file type elf64-x86-64.
        Entry point: 0x555555556660
...
        0x00005555555563e0 - 0x000055555555b001 is .text
...
(gdb) find /b 0x00005555555563e0, 0x000055555555b001, 0x00, 0x48, 0x89, 0x45, 
0xc8, 0x31, 0xc0, 0x48, 0x63, 0x05, 0x5d, 0x98, 0x00, 0x00, 0x48, 0x8d, 0x04, 
0x85, 0x0f, 0x00, 0x00, 0x00, 0x48, 0x83, 0xe0, 0xf0, 0x48, 0x29, 0xc4, 0x48, 
0x89, 0x65, 0x98, 0x48, 0x29, 0xc4, 0x31, 0xc0, 0x48, 0x89, 0x65, 0x90, 0xe8, 
0xd8, 0x3e, 0x00, 0x00, 0x31, 0xc0, 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, 0x48, 
0x8b, 0x4d, 0x98, 0x48, 0x8b, 0x55, 0x90, 0xc7
0x5555555567a9 <brute+41>
1 pattern found.

(gdb) b *(0x5555555567a9 + 42)
Breakpoint 3 at 0x5555555567d3: file unhide-linux-bruteforce.c, line 73.

(gdb) x/10xb 0x5555555567d3
0x5555555567d3 <brute+83>:      0xe8    0xd8    0x3e    0x00    0x00    0x31    
0xc0    0x66
0x5555555567db <brute+91>:      0x0f    0x1f

(gdb) info b
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x00005555555567d3 in brute at 
unhide-linux-bruteforce.c:73

(gdb) list unhide-linux-bruteforce.c:73
68         int allpids2[maxpid] ;
69         int x;
70         int y;
71         int z;
72
73         msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS 
with fork()\n") ;
74
75         // PID under 301 are reserved for kernel
76         for(x=0; x < 301; x++) 
77         {

(gdb) disassemble brute
Dump of assembler code for function brute:
   0x0000555555556780 <+0>:     push   %rbp
   0x0000555555556781 <+1>:     lea    0x5880(%rip),%rdx        # 0x55555555c008
   0x0000555555556788 <+8>:     xor    %esi,%esi
   0x000055555555678a <+10>:    mov    %rsp,%rbp
   0x000055555555678d <+13>:    push   %r15
   0x000055555555678f <+15>:    push   %r14
   0x0000555555556791 <+17>:    push   %r13
   0x0000555555556793 <+19>:    push   %r12
   0x0000555555556795 <+21>:    push   %rbx
   0x0000555555556796 <+22>:    sub    $0x68,%rsp
   0x000055555555679a <+26>:    mov    0x3a38f(%rip),%rdi        # 
0x555555590b30 <unlog>
   0x00005555555567a1 <+33>:    mov    %fs:0x28,%rax
   0x00005555555567aa <+42>:    mov    %rax,-0x38(%rbp)
   0x00005555555567ae <+46>:    xor    %eax,%eax
   0x00005555555567b0 <+48>:    movslq 0x985d(%rip),%rax        # 
0x555555560014 <maxpid>
   0x00005555555567b7 <+55>:    lea    0xf(,%rax,4),%rax
   0x00005555555567bf <+63>:    and    $0xfffffffffffffff0,%rax
   0x00005555555567c3 <+67>:    sub    %rax,%rsp
   0x00005555555567c6 <+70>:    mov    %rsp,-0x68(%rbp)
   0x00005555555567ca <+74>:    sub    %rax,%rsp
   0x00005555555567cd <+77>:    xor    %eax,%eax
   0x00005555555567cf <+79>:    mov    %rsp,-0x70(%rbp)
   0x00005555555567d3 <+83>:    callq  0x55555555a6b0 <msgln>           
<<<<<<<<<<<<<<<
   0x00005555555567d8 <+88>:    xor    %eax,%eax
   0x00005555555567da <+90>:    nopw   0x0(%rax,%rax,1)
   0x00005555555567e0 <+96>:    mov    -0x68(%rbp),%rcx
   0x00005555555567e4 <+100>:   mov    -0x70(%rbp),%rdx
...


##########


gdb -q --args unhide brute

set width 0
set pagination off
set backtrace past-main
directory /home/benutzer/source/unhide/orig/unhide-20130526
b *(brute +83)
run




root@debian:~# gdb -q --args unhide brute
Reading symbols from unhide...
Reading symbols from 
/usr/lib/debug/.build-id/41/d7d39535f738606ad3acf0611a8397925762b3.debug...
(gdb) set width 0
(gdb) set pagination off
(gdb) directory /home/benutzer/source/unhide/orig/unhide-20130526
Source directories searched: 
/home/benutzer/source/unhide/orig/unhide-20130526:$cdir:$cwd
(gdb) b brute
Breakpoint 1 at 0x2780: file unhide-linux-bruteforce.c, line 65.
(gdb) run
Starting program: /usr/sbin/unhide brute
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Unhide 20130526
Copyright © 2013 Yago Jesus & Patrick Gouin
License GPLv3+ : GNU GPL version 3 or later
http://www.unhide-forensics.info

NOTE : This version of unhide is for systems using Linux >= 2.6 

Used options: 

Breakpoint 1, brute () at unhide-linux-bruteforce.c:65
65      {
(gdb) b *(brute +83)
Breakpoint 2 at 0x5555555567d3: file unhide-linux-bruteforce.c, line 73.
(gdb) dele 1
(gdb) cont
Continuing.

Breakpoint 2, brute () at unhide-linux-bruteforce.c:73
73         msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS 
with fork()\n") ;
(gdb) stepi

Program received signal SIGSEGV, Segmentation fault.
brute () at unhide-linux-bruteforce.c:73
73         msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS 
with fork()\n") ;
(gdb) bt
#0  brute () at unhide-linux-bruteforce.c:73
#1  0x00005555555565c9 in main (argc=argc@entry=2, 
argv=argv@entry=0x7fffffffecf8) at unhide-linux.c:787
#2  0x00007ffff7e0ebbb in __libc_start_main (main=0x5555555563e0 <main>, 
argc=2, argv=0x7fffffffecf8, init=<optimized out>, fini=<optimized out>, 
rtld_fini=<optimized out>, stack_end=0x7fffffffece8) at ../csu/libc-start.c:308
#3  0x000055555555668a in _start ()
(gdb) display/i $pc
1: x/i $pc
=> 0x5555555567d3 <brute+83>:   callq  0x55555555a6b0 <msgln>

(gdb) info frame 0
Stack frame at 0x7fffffffebf0:
 rip = 0x5555555567d3 in brute (unhide-linux-bruteforce.c:73); saved rip = 
0x5555555565c9
 called by frame at 0x7fffffffec20
 source language c.
 Arglist at 0x7ffffdffeb50, args: 
 Locals at 0x7ffffdffeb50, Previous frame's sp is 0x7fffffffebf0
 Saved registers:
  rbx at 0x7fffffffebb8, rbp at 0x7fffffffebe0, r12 at 0x7fffffffebc0, r13 at 
0x7fffffffebc8, r14 at 0x7fffffffebd0, r15 at 0x7fffffffebd8, rip at 
0x7fffffffebe8
(gdb) info frame 1
Stack frame at 0x7fffffffec20:
 rip = 0x5555555565c9 in main (unhide-linux.c:787); saved rip = 0x7ffff7e0ebbb
 called by frame at 0x7fffffffece0, caller of frame at 0x7fffffffebf0
 source language c.
 Arglist at 0x7fffffffebe8, args: argc=argc@entry=2, 
argv=argv@entry=0x7fffffffecf8
 Locals at 0x7fffffffebe8, Previous frame's sp is 0x7fffffffec20
 Saved registers:
  rbx at 0x7fffffffebf8, rbp at 0x7fffffffec00, r12 at 0x7fffffffec08, r13 at 
0x7fffffffec10, rip at 0x7fffffffec18
(gdb) info frame 2
Stack frame at 0x7fffffffece0:
 rip = 0x7ffff7e0ebbb in __libc_start_main (../csu/libc-start.c:308); saved rip 
= 0x55555555668a
 called by frame at 0x0, caller of frame at 0x7fffffffec20
 source language c.
 Arglist at 0x7fffffffec18, args: main=0x5555555563e0 <main>, argc=2, 
argv=0x7fffffffecf8, init=<optimized out>, fini=<optimized out>, 
rtld_fini=<optimized out>, stack_end=0x7fffffffece8
 Locals at 0x7fffffffec18, Previous frame's sp is 0x7fffffffece0
 Saved registers:
  rbx at 0x7fffffffecb0, rbp at 0x7fffffffecb8, r12 at 0x7fffffffecc0, r13 at 
0x7fffffffecc8, r14 at 0x7fffffffecd0, rip at 0x7fffffffecd8
(gdb) info frame 3
Stack frame at 0x0:
 rip = 0x55555555668a in _start; saved rip = <not saved>
 Outermost frame: outermost
 caller of frame at 0x7fffffffece0
 Arglist at 0x7fffffffecd8, args: 
 Locals at 0x7fffffffecd8, Previous frame's sp is 0x7fffffffece8



https://stackoverflow.com/questions/37321252/check-used-stack-size-using-core-file/37327019


(gdb) print (char *)_environ - (char *)$sp
$1 = 33554880
(gdb) print/x (char *)_environ - (char *)$sp
$2 = 0x20001c0

(gdb) print/x maxpid
$4 = 0x400000

(gdb) print/x sizeof(allpids2[0])
$5 = 0x4
(gdb) print/x sizeof(allpids2[0]) * maxpid
$6 = 0x1000000
(gdb) print sizeof(allpids2[0]) * maxpid
$7 = 16777216
(gdb) print (sizeof(allpids2[0]) * maxpid)/1024
$8 = 16384
(gdb) print (sizeof(allpids2[0]) * maxpid)/1024/1024
$9 = 16



root@debian:~# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 11863
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192            <<<<<<<<<<< Just 8 MB 
stack size, but array allpids2 has 16 MB of size
cpu time               (seconds, -t) unlimited
max user processes              (-u) 11863
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
Description: Allocate pid arrays from the stack

Author: Bernhard Übelacker <bernha...@mailbox.org>
Bug-Debian: https://bugs.debian.org/945864
Forwarded: no
Last-Update: 2019-12-03

--- unhide-20130526.orig/unhide-linux-bruteforce.c
+++ unhide-20130526/unhide-linux-bruteforce.c
@@ -64,14 +64,20 @@ void *funcionThread (void *parametro)
 void brute(void) 
 {
    int i=0;
-   int allpids[maxpid] ;
-   int allpids2[maxpid] ;
+   int* allpids;
+   int* allpids2;
    int x;
    int y;
    int z;
 
    msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS with fork()\n") ;
 
+   allpids = malloc(sizeof(int)*maxpid) ;
+   allpids2 = malloc(sizeof(int)*maxpid) ;
+   if (!allpids || !allpids2) {
+      die(unlog, "Error: Cannot allocate pid arrays ! Exiting.");
+   }
+
    // PID under 301 are reserved for kernel
    for(x=0; x < 301; x++) 
    {
@@ -214,4 +220,7 @@ void brute(void)
          }
       }
    }
+
+   free(allpids);
+   free(allpids2);
 }

Reply via email to