mandibule
mandibule copied to clipboard
program stuck at "starting ..."
For my last issue: https://github.com/ixty/mandibule/issues/2 I commit the patch: https://github.com/Hackerl/mandibule/commit/92de629dee87e149481c10924d3db2a23280605f
unsigned long mandibule_beg(int aligned)
{
if(!aligned)
return (unsigned long)mandibule_beg;
unsigned long align_size = (unsigned long)mandibule_beg % 0x1000;
return (unsigned long)mandibule_beg - (align_size == 0 ? 0x1000 : align_size);
}
After successful compilation, it can run successfully, but the process is stuck.
I modified the source code to output detailed logs, and found that the program was stuck in a system call.
stuck log:
./mandibule $(pwd)/toinject $(pidof target)
> syscall: 10
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 3
> syscall: 3
> syscall: 158
> syscall: 158
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
> syscall: 18446744073709551615
after syscall 158, the output of syscall will be messy, so I guess there is a problem with the system call 158. What's interesting is that I shortened the name of the injected program "toinject" a bit, and renamed it to "toinj" and it could run successfully. success log:
./mandibule $(pwd)/toinj $(pidof target)
> syscall: 10
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 9
> syscall: 3
> syscall: 3
> syscall: 158
> syscall: 158
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 10
> syscall: 11
> syscall: 11
> syscall: 39
> syscall: 39
> syscall: 5
> syscall: 5
> syscall: 12
> syscall: 12
> syscall: 12
> syscall: 12
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 1
> syscall: 35
> syscall: 35
> syscall: 1
> syscall: 1
> syscall: 35
> syscall: 35
> syscall: 1
> syscall: 1
> syscall: 35
> syscall: 35
> syscall: 1
> syscall: 1
> syscall: 231
> shellcode executed!
> restored memory & registers
> successfully injected shellcode into pid 15313
Can continue to run after the system call 158, I am going to debug further, I will add information here later.
filename length >= 8 will trigger bug.
stuck:
Things are getting weird, I try to set the environment variable to output "ld.so" log. When i run "./mandibule ./toinject -e LD_DEBUG=all $(pidof target)", is works.
> started.
...> target pid: 22143
> arg[0]: ./toinject
> env[0]: LD_DEBUG=all
> args size: 64
> auxv len: 320
av[0]: ./toinject
env[0]: LD_DEBUG=all
> auto-detected manual mapping address 0x55820a000000
> mapping './toinject' into memory at 0x55820a000000
> reading elf file './toinject'
> loading elf at: 0x55820a000000
> seg[0] load: 0 addr 0x40 size 0x268
> seg[1] load: 0 addr 0x2a8 size 0x1c
> seg[2] load: 1 addr 0x0 size 0x680
> load segment addr 0x55820a000000 len 0x1000 => 0x55820a000000
> seg[3] load: 1 addr 0x1000 size 0x2bd
> load segment addr 0x55820a001000 len 0x1000 => 0x55820a001000
> seg[4] load: 1 addr 0x2000 size 0x158
> load segment addr 0x55820a002000 len 0x1000 => 0x55820a002000
> seg[5] load: 1 addr 0x3de8 size 0x278
> load segment addr 0x55820a003de8 len 0x1000 => 0x55820a003000
> seg[6] load: 0 addr 0x3df8 size 0x1e0
> seg[7] load: 0 addr 0x2c4 size 0x44
> seg[8] load: 0 addr 0x2038 size 0x34
> seg[9] load: 0 addr 0x0 size 0x0
> seg[10] load: 0 addr 0x3de8 size 0x218
> program base: 0x55820a000000
> max vaddr 0x55820a015000
> loading interp '/lib64/ld-linux-x86-64.so.2'
> reading elf file '/lib64/ld-linux-x86-64.so.2'
> loading elf at: 0x55820a015000
> seg[0] load: 1 addr 0x0 size 0xf08
> load segment addr 0x55820a015000 len 0x1000 => 0x55820a015000
> seg[1] load: 1 addr 0x1000 size 0x1db20
> load segment addr 0x55820a016000 len 0x1e000 => 0x55820a016000
> seg[2] load: 1 addr 0x1f000 size 0x73dc
> load segment addr 0x55820a034000 len 0x8000 => 0x55820a034000
> seg[3] load: 1 addr 0x27640 size 0x1b50
> load segment addr 0x55820a03c640 len 0x2000 => 0x55820a03c000
> seg[4] load: 0 addr 0x27e78 size 0x170
> seg[5] load: 0 addr 0x238 size 0x24
> seg[6] load: 0 addr 0x23620 size 0x6d4
> seg[7] load: 0 addr 0x0 size 0x0
> seg[8] load: 0 addr 0x27640 size 0x9c0
> program base: 0x55820a016000
> max vaddr 0x55820a04f000
> eop 0x55820a016090
> setting auxv
> set auxv[3] to 0x55820a000040
> set auxv[5] to 0xb
> set auxv[9] to 0x55820a001090
> set auxv[7] to 0x55820a000000
> eop 0x55820a016090
> starting ...
22143:
22143: WARNING: Unsupported flag value(s) of 0x8000000 in DT_FLAGS_1.
22143:
22143: file=libc.so.6 [0]; needed by ./toinject [0]
22143: find library=libc.so.6 [0]; searching
22143: search cache=/etc/ld.so.cache
22143: trying file=/lib/x86_64-linux-gnu/libc.so.6
22143:
22143: file=libc.so.6 [0]; generating link map
22143: dynamic: 0x00007fcaf7f40b80 base: 0x00007fcaf7d86000 size: 0x00000000001c0800
22143: entry: 0x00007fcaf7daa1b0 phdr: 0x00007fcaf7d86040 phnum: 12
22143:
22143: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file ./toinject [0]
22143: checking for version `GLIBC_2.3' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
22143: checking for version `GLIBC_PRIVATE' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
22143:
22143: Initial object scopes
22143: object=./toinject [0]
22143: scope 0: ./toinject /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
22143:
22143: object=linux-vdso.so.1 [0]
22143: scope 0: ./toinject /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
22143: scope 1: linux-vdso.so.1
22143:
22143: object=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: scope 0: ./toinject /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
22143:
22143: object=/lib64/ld-linux-x86-64.so.2 [0]
22143: no scope
22143:
22143:
22143: relocation processing: /lib/x86_64-linux-gnu/libc.so.6 (lazy)
22143: symbol=_res; lookup in file=./toinject [0]
22143: symbol=_res; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_res' [GLIBC_2.2.5]
22143: symbol=stderr; lookup in file=./toinject [0]
22143: symbol=stderr; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `stderr' [GLIBC_2.2.5]
22143: symbol=error_one_per_line; lookup in file=./toinject [0]
22143: symbol=error_one_per_line; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `error_one_per_line' [GLIBC_2.2.5]
22143: symbol=__morecore; lookup in file=./toinject [0]
22143: symbol=__morecore; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__morecore' [GLIBC_2.2.5]
22143: symbol=__key_encryptsession_pk_LOCAL; lookup in file=./toinject [0]
22143: symbol=__key_encryptsession_pk_LOCAL; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__key_encryptsession_pk_LOCAL' [GLIBC_2.2.5]
22143: symbol=__libpthread_freeres; lookup in file=./toinject [0]
22143: symbol=__libpthread_freeres; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
22143: symbol=__libpthread_freeres; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
...
When i run "./mandibule ./toinject -e LD_DEBUG=all $(pidof target)", modify the file name to shorter as I did before, It's stuck.
> started.
......> target pid: 22162
> arg[0]: ./to
> env[0]: LD_DEBUG=all
> args size: 58
> auxv len: 320
av[0]: ./to
env[0]: LD_DEBUG=all
> auto-detected manual mapping address 0x555e44000000
> mapping './to' into memory at 0x555e44000000
> reading elf file './to'
> loading elf at: 0x555e44000000
> seg[0] load: 0 addr 0x40 size 0x268
> seg[1] load: 0 addr 0x2a8 size 0x1c
> seg[2] load: 1 addr 0x0 size 0x680
> load segment addr 0x555e44000000 len 0x1000 => 0x555e44000000
> seg[3] load: 1 addr 0x1000 size 0x2bd
> load segment addr 0x555e44001000 len 0x1000 => 0x555e44001000
> seg[4] load: 1 addr 0x2000 size 0x158
> load segment addr 0x555e44002000 len 0x1000 => 0x555e44002000
> seg[5] load: 1 addr 0x3de8 size 0x278
> load segment addr 0x555e44003de8 len 0x1000 => 0x555e44003000
> seg[6] load: 0 addr 0x3df8 size 0x1e0
> seg[7] load: 0 addr 0x2c4 size 0x44
> seg[8] load: 0 addr 0x2038 size 0x34
> seg[9] load: 0 addr 0x0 size 0x0
> seg[10] load: 0 addr 0x3de8 size 0x218
> program base: 0x555e44000000
> max vaddr 0x555e44015000
> loading interp '/lib64/ld-linux-x86-64.so.2'
> reading elf file '/lib64/ld-linux-x86-64.so.2'
> loading elf at: 0x555e44015000
> seg[0] load: 1 addr 0x0 size 0xf08
> load segment addr 0x555e44015000 len 0x1000 => 0x555e44015000
> seg[1] load: 1 addr 0x1000 size 0x1db20
> load segment addr 0x555e44016000 len 0x1e000 => 0x555e44016000
> seg[2] load: 1 addr 0x1f000 size 0x73dc
> load segment addr 0x555e44034000 len 0x8000 => 0x555e44034000
> seg[3] load: 1 addr 0x27640 size 0x1b50
> load segment addr 0x555e4403c640 len 0x2000 => 0x555e4403c000
> seg[4] load: 0 addr 0x27e78 size 0x170
> seg[5] load: 0 addr 0x238 size 0x24
> seg[6] load: 0 addr 0x23620 size 0x6d4
> seg[7] load: 0 addr 0x0 size 0x0
> seg[8] load: 0 addr 0x27640 size 0x9c0
> program base: 0x555e44016000
> max vaddr 0x555e4404f000
> eop 0x555e44016090
> setting auxv
> set auxv[3] to 0x555e44000040
> set auxv[5] to 0xb
> set auxv[9] to 0x555e44001090
> set auxv[7] to 0x555e44000000
> eop 0x555e44016090
> starting ...
22162:
22162: WARNING: Unsupported flag value(s) of 0x8000000 in DT_FLAGS_1.
22162:
22162: file=libc.so.6 [0]; needed by ./to [0]
22162: find library=libc.so.6 [0]; searching
22162: search cache=/etc/ld.so.cache
22162: trying file=/lib/x86_64-linux-gnu/libc.so.6
22162:
22162: file=libc.so.6 [0]; generating link map
22162: dynamic: 0x00007f5d7f725b80 base: 0x00007f5d7f56b000 size: 0x00000000001c0800
22162: entry: 0x00007f5d7f58f1b0 phdr: 0x00007f5d7f56b040 phnum: 12
22162:
22162: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file ./to [0]
22162: checking for version `GLIBC_2.3' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
22162: checking for version `GLIBC_PRIVATE' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
22162:
22162: Initial object scopes
22162: object=./to [0]
22162: scope 0: ./to /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
22162:
22162: object=linux-vdso.so.1 [0]
22162: scope 0: ./to /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
22162: scope 1: linux-vdso.so.1
22162:
22162: object=/lib/x86_64-linux-gnu/libc.so.6 [0]
22162: scope 0: ./to /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
22162:
22162: object=/lib64/ld-linux-x86-64.so.2 [0]
22162: no scope
22162:
22162:
22162: relocation processing: /lib/x86_64-linux-gnu/libc.so.6 (lazy)
===============> stuck
But I removed the environment variable, the situation is just the opposite, it seems I need to learn the source code of glibc.
Screenshot:
For debugging, I defined the "nanosleep" system call in "icrt_syscall.h".
_syscall2(SYS_nanosleep,_nanosleep, int, void*, void*)
Pause the process for 30 seconds when jumping to the entry address.
struct timespec req = {};
struct timespec rem = {};
req.tv_sec = 30;
printf("pause");
_nanosleep(&req, &rem);
printf("run");
// all done
printf("> starting ...\n\n");
FIX_SP_JMP(stackptr, eop);
Then modify "pt_inject" function, detach target process when shellcode execute.
// execute code now
printf("> running shellcode..\n");
if(_ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0)
_pt_fail("> _pt_detach error\n");
printf("detach");
return 0;
During the 30-second pause time, I used gdb to attach to the target process, and then resume thread execution.
When the program is running in "ld.so", a segmentation error occurs, the error instruction is "movaps [rbp+var_70], xmm0".
The reason is that the memory parameter of the "movaps" instruction requires 16-byte alignment, but the custom fake stack does not consider this.
For debugging, I defined the "nanosleep" system call in "icrt_syscall.h".
_syscall2(SYS_nanosleep,_nanosleep, int, void*, void*)
Pause the process for 30 seconds when jumping to the entry address.
struct timespec req = {}; struct timespec rem = {}; req.tv_sec = 30; printf("pause"); _nanosleep(&req, &rem); printf("run"); // all done printf("> starting ...\n\n"); FIX_SP_JMP(stackptr, eop);
Then modify "pt_inject" function, detach target process when shellcode execute.
// execute code now printf("> running shellcode..\n"); if(_ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) _pt_fail("> _pt_detach error\n"); printf("detach"); return 0;
During the 30-second pause time, I used gdb to attach to the target process, and then resume thread execution. When the program is running in "ld.so", a segmentation error occurs, the error instruction is "movaps [rbp+var_70], xmm0".
The reason is that the memory parameter of the "movaps" instruction requires 16-byte alignment, but the custom fake stack does not consider this.
Hello Hackerl, I try the software on arm64, but I got different behavior as you mentioned, I can run it in arm64 using named "toinject", but stucked using named "toinj" Could you kindly share your test code which support me to debug the issues? Thanks a lots.
-
Failed using named "toinj"
-
Success using named "toinject"
For debugging, I defined the "nanosleep" system call in "icrt_syscall.h".
_syscall2(SYS_nanosleep,_nanosleep, int, void*, void*)
Pause the process for 30 seconds when jumping to the entry address.
struct timespec req = {}; struct timespec rem = {}; req.tv_sec = 30; printf("pause"); _nanosleep(&req, &rem); printf("run"); // all done printf("> starting ...\n\n"); FIX_SP_JMP(stackptr, eop);
Then modify "pt_inject" function, detach target process when shellcode execute.
// execute code now printf("> running shellcode..\n"); if(_ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) _pt_fail("> _pt_detach error\n"); printf("detach"); return 0;
During the 30-second pause time, I used gdb to attach to the target process, and then resume thread execution. When the program is running in "ld.so", a segmentation error occurs, the error instruction is "movaps [rbp+var_70], xmm0".
The reason is that the memory parameter of the "movaps" instruction requires 16-byte alignment, but the custom fake stack does not consider this.
Hello Hackerl, I try the software on arm64, but I got different behavior as you mentioned, I can run it in arm64 using named "toinject", but stucked using named "toinj" Could you kindly share your test code which support me to debug the issues? Thanks a lots.
- Failed using named "toinj"
![]()
- Success using named "toinject"
![]()
Hello, the reason for this problem is that the fake stack is not aligned to 16 bytes. I fixed this error and dealt with some other bugs. look here: https://github.com/Hackerl/mandibule In addition, I refactored the entire project, but currently only supports x64. If you are interested, you can add support for arm64. look here: https://github.com/Hackerl/pangolin
For debugging, I defined the "nanosleep" system call in "icrt_syscall.h".
_syscall2(SYS_nanosleep,_nanosleep, int, void*, void*)
Pause the process for 30 seconds when jumping to the entry address.
struct timespec req = {}; struct timespec rem = {}; req.tv_sec = 30; printf("pause"); _nanosleep(&req, &rem); printf("run"); // all done printf("> starting ...\n\n"); FIX_SP_JMP(stackptr, eop);
Then modify "pt_inject" function, detach target process when shellcode execute.
// execute code now printf("> running shellcode..\n"); if(_ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) _pt_fail("> _pt_detach error\n"); printf("detach"); return 0;
During the 30-second pause time, I used gdb to attach to the target process, and then resume thread execution. When the program is running in "ld.so", a segmentation error occurs, the error instruction is "movaps [rbp+var_70], xmm0".
The reason is that the memory parameter of the "movaps" instruction requires 16-byte alignment, but the custom fake stack does not consider this.
Hello Hackerl, I try the software on arm64, but I got different behavior as you mentioned, I can run it in arm64 using named "toinject", but stucked using named "toinj" Could you kindly share your test code which support me to debug the issues? Thanks a lots.
- Failed using named "toinj"
![]()
- Success using named "toinject"
![]()
hello, I just supported multiple cpu architectures, aarch64 has been tested, and the rest of the architecture is still being prepared. https://github.com/Hackerl/pangolin/tree/arch