Wrong Memory Adresses regarding the code x86 using GDB [duplicate] - linux

I'm trying to debug this simple C program:
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello\n");
}
But when I disassemble the main function I get this:
(gdb) disas main
Dump of assembler code for function main:
0x000000000000063a <+0>: push rbp
0x000000000000063b <+1>: mov rbp,rsp
0x000000000000063e <+4>: sub rsp,0x10
0x0000000000000642 <+8>: mov DWORD PTR [rbp-0x4],edi
0x0000000000000645 <+11>: mov QWORD PTR [rbp-0x10],rsi
0x0000000000000649 <+15>: lea rdi,[rip+0x94] # 0x6e4
0x0000000000000650 <+22>: call 0x510 <puts#plt>
0x0000000000000655 <+27>: mov eax,0x0
0x000000000000065a <+32>: leave
0x000000000000065b <+33>: ret
End of assembler dump.
And this is already pretty strange because addresses starts with a prefix of 4... for 32 bit executables and 8... for 64 bit executables I think.
But going on I then put a breakpoint:
(gdb) b *0x0000000000000650
Breakpoint 1 at 0x650
I run it and I get this error message:
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x650

Your code was most probably compiled as Position-Independent Executable (PIE) to allow Address Space Layout Randomization (ASLR). On some systems, gcc is configured to create PIEs by default (that implies the options -pie -fPIE being passed to gcc).
When you start GDB to debug a PIE, it starts reading addresses from 0, since your executable was not started yet, and therefore not relocated (in PIEs, all addresses including the .text section are relocatable and they start at 0, similar to a dynamic shared object). This is a sample output:
$ gcc -o prog main.c -pie -fPIE
$ gdb -q prog
Reading symbols from prog...(no debugging symbols found)...done.
gdb-peda$ disassemble main
Dump of assembler code for function main:
0x000000000000071a <+0>: push rbp
0x000000000000071b <+1>: mov rbp,rsp
0x000000000000071e <+4>: sub rsp,0x10
0x0000000000000722 <+8>: mov DWORD PTR [rbp-0x4],edi
0x0000000000000725 <+11>: mov QWORD PTR [rbp-0x10],rsi
0x0000000000000729 <+15>: lea rdi,[rip+0x94] # 0x7c4
0x0000000000000730 <+22>: call 0x5d0 <puts#plt>
0x0000000000000735 <+27>: mov eax,0x0
0x000000000000073a <+32>: leave
0x000000000000073b <+33>: ret
End of assembler dump.
As you can see, this shows a similar output to yours, with .text adresses starting at low values.
Relocation takes place once you start your executable, so after that, your code will be placed at some random address in your process memory:
gdb-peda$ start
...
gdb-peda$ disassemble main
Dump of assembler code for function main:
0x00002b1c8f17271a <+0>: push rbp
0x00002b1c8f17271b <+1>: mov rbp,rsp
=> 0x00002b1c8f17271e <+4>: sub rsp,0x10
0x00002b1c8f172722 <+8>: mov DWORD PTR [rbp-0x4],edi
0x00002b1c8f172725 <+11>: mov QWORD PTR [rbp-0x10],rsi
0x00002b1c8f172729 <+15>: lea rdi,[rip+0x94] # 0x2b1c8f1727c4
0x00002b1c8f172730 <+22>: call 0x2b1c8f1725d0 <puts#plt>
0x00002b1c8f172735 <+27>: mov eax,0x0
0x00002b1c8f17273a <+32>: leave
0x00002b1c8f17273b <+33>: ret
End of assembler dump.
As you can see, the addresses now take "real" values that you can set breakpoints to. Note that usually you will still not see the effect of ASLR in GDB though, since it disables randomization by default (debugging a program with randomized location would be cumbersome). You can check this with show disable-randomization. If you really want to see the effects of ASLR in your PIE, set disable-randomization off. Then every run will relocate your code to random addresses.
So the bottom line is: When debugging PIE code, start your program in GDB first and then figure out the addresses.
Alternatively, you can explicitly disable the creation of PIE code and compile your application using gcc filename.c -o filename -no-pie -fno-PIE.
My system does not enforce PIE creation by default, so unfortunately I don't know about the implications of disabling PIE on such a system (would be glad to see comments on that).
For a more comprehensive explanation of position-independent code (PIC) in general (which is of utmost importance for shared libraries), have a look at Ulrich Drepper's paper "How to Write Shared Libraries".

Related

How can I work around gdb w/gef giving me "No function contains specified address"?

I am debugging a program using gdb with the gef extension. I am using GNU gdb (GDB) Fedora 12.1-1.fc36. The program I am debugging calls setvbuf and as it's dynamically linked, a call instruction occurs into the setvbuf#PLT procedure linkage table. There, I see the following:
→ 0x804859c <main+18> call 0x8048450 <setvbuf#plt>
↳ 0x8048450 <setvbuf#plt+0> jmp DWORD PTR ds:0x8049a38
0x8048456 <setvbuf#plt+6> push 0x38
0x804845b <setvbuf#plt+11> jmp 0x80483d0
When I issue the command disass 0x8049a38, gdb properly shows me the entry in the setvbuf#plt.got. However, when I issue disass 0x80483d0, gdb tells me: No function contains specified address.. I do not understand this because when I do vmmap 0x80483d0, gdb recognizes that address is indeed in the code section of my own program. Stranger, when I finally step into that jump, there IS code there and now gdb disassembles it just fine:
→ 0x80483d0 push DWORD PTR ds:0x8049a14
0x80483d6 jmp DWORD PTR ds:0x8049a18
0x80483dc add BYTE PTR [eax], al
0x80483de add BYTE PTR [eax], al
0x80483e0 <printf#plt+0> jmp DWORD PTR ds:0x8049a1c
0x80483e6 <printf#plt+6> push 0x0
0x80483eb <printf#plt+11> jmp 0x80483d0
0x80483f0 <fflush#plt+0> jmp DWORD PTR ds:0x8049a20
0x80483f6 <fflush#plt+6> push 0x8
0x80483fb <fflush#plt+11> jmp 0x80483d0
I know there's a bit of funny business that occurs with the whole PLT/GOT thunk table thing, but is there any way to force disassembly even if something is "not part of a function?"

GDB message "not yet allocated storage for thread-local variables"

Debugging a NASM shared object with gdb, I get a segmentation fault when a thread accesses its thread-local variable. When I print the value of the thread-local variable with gdb, it responds:
(gdb) p MQ_FDes_Core
The inferior has not yet allocated storage for thread-local variables in the shared library `/opt/ThTest/TLS_Test.so' for Thread 0x7fffeaf26700 (LWP 4317).
where MQ_FDes_Core is the thread local variable. If I execute the line "mov [MQ_FDes_Core],rax" gdb generates a segmentation fault because the tls has not yet been initialized.
The code section where this occurs is:
lea rdi,[MQ_Name]
mov rsi,rax
call mq_open wrt ..plt
mov [MQ_FDes_Core],rax
The disassembly of that section (using Agner Fog's objconv):
Open_message_queue:
lea rdi, [rel MQ_Name] ; 1367 _ 48: 8D. 3D, 0020230A(rel)
mov rsi, rax ; 136E _ 48: 89. C6
call ?_014 ; 1371 _ E8, FFFFFB9A(rel)
mov qword [rel MQ_FDes_Core], rax ; 1376 _ 48: 89. 05, 002017E3(rel)
The tdata is allocated in the .tdata section:
section .tdata align=16
MQ_FDes_Core: dq 0
The NASM 2.13.02 manual section "7.9.4 Thread Local Storage in ELF: elf Special Symbols and WRT" says to write it like this for ELF64:
mov rax,[rel MQ_FDes_Core wrt ..gottpoff]
mov rcx,[fs:rax]
But with that the NASM assembler says, "error: parser: expecting ]" at the first line.
I link with ld against -ldl, -lpthread and -lrt.
I've researched a number of web resources including Ulrich Drepper's "ELF Handling For Thread-Local Storage" but I don't yet know how to correct this. Much of it focuses on C or C++ but this is NASM.
Thanks for any ideas on initializing thread local storage in a dynamically loaded shared object.
UPDATE -- A MINIMAL EXAMPLE shared object (build into a PIE executable):
default rel
section .tdata align=16
MQ_FDes_Core: dq 0
section .text
global main
main:
mov qword [MQ_FDes_Core], 87
ret
Build with nasm -f elf64 tls.asm && gcc -pie tls.o
(gdb) start
Temporary breakpoint 1 at 0x1120
Starting program: /tmp/a.out
Temporary breakpoint 1, 0x0000555555555120 in main ()
(gdb) p MQ_FDes_Core
Cannot find thread-local storage for process 642417, executable file /tmp/a.out:
Cannot find thread-local variables on this target

Assembly x64 getcwd() Not Outputting

I've just started learning/using Assembly x64 on Linux, and am trying to call getcwd() with call. After attempting to call the getcwd() function, I am also trying to output the result which is not working and I do not understand why. Any pointers/help would be really appreciated. Sorry if its a stupid question. I've looked online for examples but haven't found any that help me specifically. Many thanks. Here is the code:
section .text
global _start
extern getcwd
_start:
mov rdi,rbx
mov rsi,128
call getcwd wrt ..plt
mov rax,1
mov rdi,1
mov rsi,rbx
mov rdx,128
syscall
mov rax,60
mov rdi,0
syscall
I compile with:
nasm -f elf64 -o file.o file.asm
gcc -nostdlib -v -o file file.o -lc
./file
And nothing is shown
Here is a possible implementation that allocates space on the stack. I also switched to main and puts:
global main
extern getcwd
extern puts
main:
sub rsp, 128+8 ; buffer + alignment
mov rdi, rsp
mov rsi, 128
call getcwd wrt ..plt
call puts wrt ..plt
add rsp, 128+8
ret
This code
mov rdi,rbx
mov rsi,128
call getcwd wrt ..plt
is equivalent to C code getcwd(__undefined__, 128);, where __undefined__ is some value that happens to be in ebx on entry to _start. On my system it appeared to be NULL, which to getcwd signalizes that no buffer is passed (regardless of its size being 128).
The getcwd function then returns pointer to the newly-allocated buffer (as an extension to POSIX, see man 3 getcwd). Your subsequent mov rax,1 overwrites this address with the system call, and subsequent instructions pass the value in ebx as the buffer to the write syscall. Since it was NULL before, by the calling convention it remains such, and you call write(1,NULL,128);, which returns EFAULT and writes nothing.

Why I cannot single stepping into aeskeygenassist instruction in self-modifying code?

I tried implementing aes128 encryption using assembly language, my final goal is to find out the final value. when debugging (using single stepping), the debugger stops at the 0x8048074 address.
Here the code :
global _start
section .text
_start:
pxor xmm2, xmm2
pxor xmm3, xmm3
mov bx, 0x36e5
mov ah, 0x73
roundloop:
shr ax, 7
div bl
mov byte [sdfsdf+5], ah
sdfsdf:
aeskeygenassist xmm1, xmm0, 0x45
pshufd xmm1, xmm1, 0xff
shuffle:
shufps xmm2, xmm0, 0x10
pxor xmm0, xmm2
xor byte [shuffle+3], 0x9c
js short shuffle
pxor xmm0, xmm1
cmp ah, bh
jz short lastround
aesenc xmm3, xmm0
jmp short roundloop
lastround:
aesenclast xmm3, xmm0
ret
Debugger stuck at here, I cannot single-stepping to 0x804807a
[-------------------------------------code-------------------------------------]
0x804806c <_start+12>: mov ah,0x73
0x804806e <roundloop>: shr ax,0x7
0x8048072 <roundloop+4>: div bl
=> 0x8048074 <roundloop+6>: mov BYTE PTR ds:0x804807f,ah
0x804807a <sdfsdf>: aeskeygenassist xmm1,xmm0,0x45
0x8048080 <sdfsdf+6>: pshufd xmm1,xmm1,0xff
0x8048085 <shuffle>: shufps xmm2,xmm0,0x10
0x8048089 <shuffle+4>: pxor xmm0,xmm2
I'm using peda plugin for GDB.
EDIT :
Sorry, I don't mention the error message, error message is Segmentation fault at this instruction mov BYTE PTR ds:0x804807f,ah
I assume you forgot to link with --omagic to make the .text section writable.
So mov BYTE PTR ds:0x804807f,ah segfaults, and it's right before aeskeygenassist. You can't keep single-stepping after your program crashes. (You have no handler for SIGSEGV, and the default action is to terminate your program).
When I tried this on my desktop out of curiosity, I can imagine interpreting the behaviour as single-stepping getting "stuck" before aeskeygenassist, if I ignore the segfault message!!! and the fact that trying again says "the program is no longer running".
From a GDB session:
(gdb) layout reg
(gdb) starti # like run with an implicit breakpoint on the first instruction
(gdb) si
0x0000000000401004 in _start ()
0x0000000000401008 in _start () ## I kept pressing return to repeat the command
0x000000000040100c in _start ()
0x000000000040100e in roundloop ()
0x0000000000401012 in roundloop ()
0x0000000000401014 in roundloop () # the MOV store
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401014 in roundloop () # still pointing at the MOV store
Notice that RIP is still pointing at the mov. 0x8048074 in your 32-bit build, 0x401014 in my 64-bit build of the same source.
From the ld manual:
-N
--omagic
Set the text and data sections to be readable and writable. Also, do not page-align the data segment, and disable linking against
shared
libraries. If the output format supports Unix style magic numbers, mark the output as "OMAGIC". Note: Although a writable text
section is
allowed for PE-COFF targets, it does not conform to the format specification published by Microsoft.
Your code works fine for me if I link with:
nasm -felf64 aes.asm &&
ld --omagic aes.o -o aes
Alternatively, you could make an mprotect system call to give the page containing this code PROT_READ|PROT_WRITE|PROT_EXEC.
GDB's layout reg disassembly window even updates disassembly for aeskeygenassist after its immediate is modified by store.
Also note that Self-Modifying Code (SMC) is extremely slow on modern x86. Full pipeline nuke after every store near instructions being executed. You'd be much better off unrolling with an assembler macro.
Also, you can't ret from _start under Linux; it's not a function. The stack pointer points to argc, not a return address. Make an _exit system call with int 0x80 for 32-bit code. When I say "works" I meant it reaches that ret and segfaults on code-fetch from address 1 after popping argc into RIP.
Also, use default rel for RIP-relative addressing of the store; it's more compact. Or I guess you're building a 32-bit executable out of this for some reason, based on your code addresses. I didn't notice that at first, that's why I tested as a 64-bit executable. Fortunately you used labels correctly, and aeskeygenassist is the same length in both modes, so it still works.

Segfault when doing syscall using GNU assember

I'm trying to understand why as behaves differently than nasm when doing syscalls on the assembly level. Because I'm a glutton for punishment, I'm using Intel syntax. Here's my program:
.intel_syntax noprefix
.section .rodata
.LC0:
.string "Hello world!\n"
.text
.globl _start
.type _start, #function
_start:
mov edx, 13
mov ecx, OFFSET FLAT:.LC0
mov eax, 4
int 0x80
ret
I assemble with as -o prog.o prog.s and link with ld -s -o prog prog.o.
But when I run it, I get:
$ ./prog
Hello world!
Segmentation fault (core dumped)
GDB is not particularly helpful here. When I stepi on ret, it says Cannot access memory at address 0x1. Which is puzzling, because the value of ESP is:
(gdb) info registers esp
info registers esp
esp 0xbffff660 0xbffff660
Why does this program segfault?
Because it never exits properly. _start doesn't have a parent stack frame, so returning from it will cause a crash.
You can return from main to have the standard library's _start implementation call exit for you, but if you're writing your own _start, you need to call exit yourself, as there's no parent stack frame to return to.

Resources