How to generate the backtrace by looking at the stack values? - linux

Quiz : How to generate the backtrace by looking at the stack values?
0xf3e2de34 f3e2de70 c0135351 401ef021 00000000 p.bsQS...p......
0xf3e2de44 f3e2de81 00000021 f3e2c000 f7950924 ..bs......bs...w
0xf3e2de54 00000000 401ef000 00000246 00000246 .....p..F...F...
0xf3e2de64 00000001 00000001 f7950000 f3e2df18 ...........w..bs
0xf3e2de74 c02898b5 322d7875 23203235 00007820 5...ux.252...x..
0xf3e2de84 f3e2de98 00000000 f7950bd0 bffff0ec ..bs....P..wlp..
0xf3e2de94 c70cf660 00000000 00000000 bffff0ec .v.G........lp..
0xf3e2dea4 f3e2c000 f7950930 7fffffff 00000000 ..bs0..w........
0xf3e2deb4 00000000 00000001 00000000 bffff07b .............p..
0xf3e2dec4 f5cfd880 bffff07b 00000000 f5f24740 .XOu.p.......Gru
0xf3e2ded4 c0124f87 00000000 00000000 00200200 .O..............
0xf3e2dee4 f3e2defc 067b3067 00000000 f5f24740 ..bsg0.......Gru
0xf3e2def4 c0124f87 f7950934 f7950934 c028331b .O..4..w4..w.3..
0xf3e2df04 00000000 c01b0fe8 f5cfd880 f7950000 ....h....XOu...w
0xf3e2df14 fffffffb f3e2df50 c0283642 00000001 ....P.bsB6......
0xf3e2df24 00000001 00000001 f3e2c000 f6fe30d0 ..........bsP0.v
Hint - the current function can always be determined from EIP
I found this question at kernelnewbies/ABI documentation.
I really dont understand the hint given there?(Maybe because i have no idea about this thing).
Could somebody explain me how to solve these kinda questions.

In this case, you can do it quite reliably, since that code has been compiled with frame pointers enabled.
What you need to know:
EIP is a register that points at the next instruction to execute.
When calling a function, the arguments and then EIP (so the called function knows where to return to) are saved on the stack.
When the compiler has been told (explicitly or implicitly) to use frame pointers, it then saves the frame pointer (in the EBP register) on the stack (so it can later restore the frame pointer to the value it had on the calling function), and then sets the frame pointer to point to the current top of the stack. This allows accessing easily arguments and local variables from a known point of reference (the frame pointer), and greatly simplifies debugging.
Then, space is reserved for local variables, and the function is executed.
When returning from the function, the previous frame pointer and instruction pointer are restored.
So, to generate a backtrace, you would follow the frame pointers, looking at the corresponding saved EIPS. So:
current function was called from c0135351
follow f3e2de70 → was called from c02898b5
follow f3e2df18 → was called from c0283642
Of course, this was the easy case. When you don't have frame pointers, you have to guess whether a given value on the stack corresponds to an instruction pointer.
The missing part is how to translate this numbers to function names. Having an unstripped vmlinux (note the x, not a z) file is invaluable. System.map just contains some symbols, so very often you'll only end up knowing that the relevant function was between function A and function B.
Edit:
A function call on x86 looks something like:
...
int main() add $-0x8,%esp ; alignment
{ push $0x2 ; arg 2
... push $0x1 ; arg 1
func(1, 2); call func ; function call
... add $0x10,%esp ; pop args from stack
} ...
And the called function looks something like:
void func(int arg1, int arg2) push %ebp ;\
{ mov %esp,%ebp ;/ create stack frame
int local1; sub $0x18,%esp ; reserves space
... ...
} mov %ebp,%esp ;\
pop %ebp ;/ destroys frame
ret ; returns
So, the stack will look similar to:
: :
+-----------+
: alignment :
+-----------+
12(%ebp) | arg2 |
+-----------+
8(%ebp) | arg1 |
+-----------+
4(%ebp) | ret | -----> return address
+-----------+
(%ebp) | ebp | -----> previous ebp
+-----------+
-4(%ebp) | local1 | -----> local vars
+-----------+
: alignment :
+-----------+
: :
(Lower addresses are lower on the ASCII-art)
So, if you keep following the saved EBP pointers, you can get the saved EIP pointers (ret above), which point to instructions in the call chain (in the return chain, to be precise).

The EIP is the instruction pointer I think - it holds the address of the instruction being executed at the moment.

Related

Where is segment %fs for static elf images setup?

I'm trying to figure out how the %fs register is initialized
when creating a elf image by hand.
The simple snippet I'd like to run is:
.text
nop
movq %fs:0x28, %rax;
1: jmp 1b
Which should read at offset 0x28 in the %fs segment. Normally this is where the stack canary is stored. Because I create the elf image by hand the %fs segment is not setup at all by my code this fails expectedly(?) .
Here is how I create the elf image:
0000000000000000 <.text>:
0: 90 nop
1: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
8: 00 00
a: eb fe jmp 0xa
I create the .text segment via
echo 9064488b042528000000ebfe | xxd -r -p > r2.bin
Then I convert to elf:
ld -b binary -r -o raw.elf r2.bin
objcopy --rename-section .data=.text --set-section-flags .data=alloc,code,load raw.elf
At that point raw.elf contains my instructions. I then link with
ld -T raw.ld -o out.elf -M --verbose where raw.ld is:
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_entry)
PHDRS {
phdr4000000 PT_LOAD;
}
SECTIONS
{
_entry = 0x4000000;
.text 0x4000000 : { raw.elf (.text) } :phdr4000000
}
I can now start out.elf with gdb:
gdb --args out.elf
and set a breakpoint at 0x4000000:
(gdb)break *0x4000000
(gdb)run
The first nop can be stepped via stepi, however the stack canary read mov %fs:0x28,%rax segfaults.
I suppose that is expected given that maybe the OS is not setting up %fs.
For a simple m.c: int main() { return 0; } program compiled with gcc --static m.c -o m I can read from %fs. Adding:
long can()
{
long v = 0;
__asm__("movq %%fs:0x28, %0;"
: "=r"(val)::);
return v;
}
lets me read from %fs - even though I doubt that %fs:28 is setup because ld.so is not run (it is a static image).
Question:
Can anyone point out where %fs is setup in the c runtime for static images?
You need to call arch_prctl with an ARCH_SET_FS argument before you can use the %fs segment prefix. You will have to allocate the backing store somewhere (brk, mmap, or an otherwise unused part of the stack).
glibc does this in __libc_setup_tls in csu/libc-tls.c for statically linked binaries, hidden behind the TLS_INIT_TP macro.

Understanding how $ works in assembly [duplicate]

len: equ 2
len: db 2
Are they the same, producing a label that can be used instead of 2? If not, then what is the advantage or disadvantage of each declaration form? Can they be used interchangeably?
The first is equate, similar to C's:
#define len 2
in that it doesn't actually allocate any space in the final code, it simply sets the len symbol to be equal to 2. Then, when you use len later on in your source code, it's the same as if you're using the constant 2.
The second is define byte, similar to C's:
int len = 2;
It does actually allocate space, one byte in memory, stores a 2 there, and sets len to be the address of that byte.
Here's some pseudo-assembler code that shows the distinction:
line addr code label instruction
---- ---- -------- ----- -----------
1 0000 org 1234h
2 1234 elen equ 2
3 1234 02 dlen db 2
4 1235 44 02 00 mov ax, elen
5 1238 44 34 12 mov ax, dlen
Line 1 simply sets the assembly address to be 1234h, to make it easier to explain what's happening.
In line 2, no code is generated, the assembler simply loads elen into the symbol table with the value 2. Since no code has been generated, the address does not change.
Then, when you use it on line 4, it loads that value into the register.
Line 3 shows that db is different, it actually allocates some space (one byte) and stores the value in that space. It then loads dlen into the symbol table but gives it the value of that address 1234h rather than the constant value 2.
When you later use dlen on line 5, you get the address, which you would have to dereference to get the actual value 2.
Summary
NASM 2.10.09 ELF output:
db does not have any magic effects: it simply outputs bytes directly to the output object file.
If those bytes happen to be in front of a symbol, the symbol will point to that value when the program starts.
If you are on the text section, your bytes will get executed.
Weather you use db or dw, etc. that does not specify the size of the symbol: the st_size field of the symbol table entry is not affected.
equ makes the symbol in the current line have st_shndx == SHN_ABS magic value in its symbol table entry.
Instead of outputting a byte to the current object file location, it outputs it to the st_value field of the symbol table entry.
All else follows from this.
To understand what that really means, you should first understand the basics of the ELF standard and relocation.
SHN_ABS theory
SHN_ABS tells the linker that:
relocation is not to be done on this symbol
the st_value field of the symbol entry is to be used as a value directly
Contrast this with "regular" symbols, in which the value of the symbol is a memory address instead, and must therefore go through relocation.
Since it does not point to memory, SHN_ABS symbols can be effectively removed from the executable by the linker by inlining them.
But they are still regular symbols on object files and do take up memory there, and could be shared amongst multiple files if global.
Sample usage
section .data
x: equ 1
y: db 2
section .text
global _start
_start:
mov al, x
; al == 1
mov al, [y]
; al == 2
Note that since the symbol x contains a literal value, no dereference [] must be done to it like for y.
If we wanted to use x from a C program, we'd need something like:
extern char x;
printf("%d", &x);
and set on the asm:
global x
Empirical observation of generated output
We can observe what we've said before with:
nasm -felf32 -o equ.o equ.asm
ld -melf_i386 -o equ equ.o
Now:
readelf -s equ.o
contains:
Num: Value Size Type Bind Vis Ndx Name
4: 00000001 0 NOTYPE LOCAL DEFAULT ABS x
5: 00000000 0 NOTYPE LOCAL DEFAULT 1 y
Ndx is st_shndx, so we see that x is SHN_ABS while y is not.
Also see that Size is 0 for y: db in no way told y that it was a single byte wide. We could simply add two db directives to allocate 2 bytes there.
And then:
objdump -dr equ
gives:
08048080 <_start>:
8048080: b0 01 mov $0x1,%al
8048082: a0 88 90 04 08 mov 0x8049088,%al
So we see that 0x1 was inlined into instruction, while y got the value of a relocation address 0x8049088.
Tested on Ubuntu 14.04 AMD64.
Docs
http://www.nasm.us/doc/nasmdoc3.html#section-3.2.4:
EQU defines a symbol to a given constant value: when EQU is used, the source line must contain a label. The action of EQU is to define the given label name to the value of its (only) operand. This definition is absolute, and cannot change later. So, for example,
message db 'hello, world'
msglen equ $-message
defines msglen to be the constant 12. msglen may not then be redefined later. This is not a preprocessor definition either: the value of msglen is evaluated once, using the value of $ (see section 3.5 for an explanation of $) at the point of definition, rather than being evaluated wherever it is referenced and using the value of $ at the point of reference.
See also
Analogous question for GAS: Difference between .equ and .word in ARM Assembly? .equiv seems to be the closes GAS equivalent.
equ: preprocessor time. analogous to #define but most assemblers are lacking an #undef, and can't have anything but an atomic constant of fixed number of bytes on the right hand side, so floats, doubles, lists are not supported with most assemblers' equ directive.
db: compile time. the value stored in db is stored in the binary output by the assembler at a specific offset. equ allows you define constants that normally would need to be either hardcoded, or require a mov operation to get. db allows you to have data available in memory before the program even starts.
Here's a nasm demonstrating db:
; I am a 16 byte object at offset 0.
db '----------------'
; I am a 14 byte object at offset 16
; the label foo makes the assembler remember the current 'tell' of the
; binary being written.
foo:
db 'Hello, World!', 0
; I am a 2 byte filler at offset 30 to help readability in hex editor.
db ' .'
; I am a 4 byte object at offset 16 that the offset of foo, which is 16(0x10).
dd foo
An equ can only define a constant up to the largest the assembler supports
example of equ, along with a few common limitations of it.
; OK
ZERO equ 0
; OK(some assemblers won't recognize \r and will need to look up the ascii table to get the value of it).
CR equ 0xD
; OK(some assemblers won't recognize \n and will need to look up the ascii table to get the value of it).
LF equ 0xA
; error: bar.asm:2: warning: numeric constant 102919291299129192919293122 -
; does not fit in 64 bits
; LARGE_INTEGER equ 102919291299129192919293122
; bar.asm:5: error: expression syntax error
; assemblers often don't support float constants, despite fitting in
; reasonable number of bytes. This is one of the many things
; we take for granted in C, ability to precompile floats at compile time
; without the need to create your own assembly preprocessor/assembler.
; PI equ 3.1415926
; bar.asm:14: error: bad syntax for EQU
; assemblers often don't support list constants, this is something C
; does support using define, allowing you to define a macro that
; can be passed as a single argument to a function that takes multiple.
; eg
; #define RED 0xff, 0x00, 0x00, 0x00
; glVertex4f(RED);
; #undef RED
;RED equ 0xff, 0x00, 0x00, 0x00
the resulting binary has no bytes at all because equ does not pollute the image; all references to an equ get replaced by the right hand side of that equ.

ARM inline asm: exit system call with value read from memory

Problem
I want to execute the exit system call in ARM using inline assembly on a Linux Android device, and I want the exit value to be read from a location in memory.
Example
Without giving this extra argument, a macro for the call looks like:
#define ASM_EXIT() __asm__("mov %r0, #1\n\t" \
"mov %r7, #1\n\t" \
"swi #0")
This works well.
To accept an argument, I adjust it to:
#define ASM_EXIT(var) __asm__("mov %r0, %0\n\t" \
"mov %r7, #1\n\t" \
"swi #0" \
: \
: "r"(var))
and I call it using:
#define GET_STATUS() (*(int*)(some_address)) //gets an integer from an address
ASM_EXIT(GET_STATUS());
Error
invalid 'asm': operand number out of range
I can't explain why I get this error, as I use one input variable in the above snippet (%0/var). Also, I have tried with a regular variable, and still got the same error.
Extended-asm syntax requires writing %% to get a single % in the asm output. e.g. for x86:
asm("inc %eax") // bad: undeclared clobber
asm("inc %%eax" ::: "eax"); // safe but still useless :P
%r7 is treating r7 as an operand number. As commenters have pointed out, just omit the %s, because you don't need them for ARM, even with GNU as.
Unfortunately, there doesn't seem to be a way to request input operands in specific registers on ARM, the way you can for x86. (e.g. "a" constraint means eax specifically).
You can use register int var asm ("r7") to force a var to use a specific register, and then use an "r" constraint and assume it will be in that register. I'm not sure this is always safe, or a good idea, but it appears to work even after inlining. #Jeremy comments that this technique was recommended by the GCC team.
I did get some efficient code generated, which avoids wasting an instruction on a reg-reg move:
See it on the Godbolt Compiler Explorer:
__attribute__((noreturn)) static inline void ASM_EXIT(int status)
{
register int status_r0 asm ("r0") = status;
register int callno_r7 asm ("r7") = 1;
asm volatile("swi #0\n"
:
: "r" (status_r0), "r" (callno_r7)
: "memory" // any side-effects on shared memory need to be done before this, not delayed until after
);
// __builtin_unreachable(); // optionally let GCC know the inline asm doesn't "return"
}
#define GET_STATUS() (*(int*)(some_address)) //gets an integer from an address
void foo(void) { ASM_EXIT(12); }
push {r7} # # gcc is still saving r7 before use, even though it sees the "noreturn" and doesn't generate a return
movs r0, #12 # stat_r0,
movs r7, #1 # callno,
swi #0
# yes, it literally ends here, after the inlined noreturn
void bar(int status) { ASM_EXIT(status); }
push {r7} #
movs r7, #1 # callno,
swi #0 # doesn't touch r0: already there as bar()'s first arg.
Since you always want the value read from memory, you could use an "m" constraint and include a ldr in your inline asm. Then you wouldn't need the register int var asm("r0") trick to avoid a wasted mov for that operand.
The mov r7, #1 might not always be needed either, which is why I used the register asm() syntax for it, too. If gcc wants a 1 constant in a register somewhere else in a function, it can do it in r7 so it's already there for the ASM_EXIT.
Any time the first or last instructions of a GNU C inline asm statement are mov instructions, there's probably a way to remove them with better constraints.

Reading /proc/pid/mem from ptraced process returns EOF

Context
I've been working in a program for my final assignment and I've found the following strange behaviour.
I've coded a tracer in order to be able to read/write memory from child processes. My intention is to read the currently executed instruction at a given point, then disassemble it in order to get some information about memory operands and such.
For testing purposes a simple HelloWorld written in C is used.
Information
The code of the tracer I've written, albeit simplified in order to be more understandable, is this:
size_t tracer::readMem(ADDR_t offset, char *buff, size_t len) {
REQUIRE(_state != TRCS_UNINITIALISED);
if (_memsdescr < 0 || fcntl(_memsdescr, F_GETFL) < 0) {
_memsdescr = open(("/proc/" + to_string(_child_pid_t) + "/mem").c_str(), O_LARGEFILE);
if (_memsdescr < 0) {
logmanager::getInstance ().emplaceBasicLogger ("tracer")
.log ( SLVL_ERROR, "Process\' memory could not be "
" opened. \n");
PANIC;
} else {
logmanager::getInstance ().emplaceBasicLogger ("tracer")
.logfmt ( SLVL_DEBUG, "Opened process' memory. %lx bytes long\n",
lseek(_memsdescr, 0, SEEK_END));
}
}
ASSERT(offset <= lseek(_memsdescr, 0, SEEK_END));
int ret = pread(_memsdescr, buff, len, offset);
if (ret < 0) {
logmanager::getInstance ().emplaceBasicLogger ("tracer")
.logfmt( SLVL_ERROR, "Error reading from memory descriptor: %s\n", sys_errlist[errno]);
}
return ret;
}
The code that controls the exectution is the following. Basically all it does is to read 15 bytes chunks from /proc/mem. The address of those chunks is obtained by getting the value of the RIP (instruction pointer) after a call to ptrace(PTRACE_SINGLESTEP). This means all the memory I try to read should be mapped in the process' memory space.
trc.load (filename);
trc.launchProgram();
cout << " Started with pid " << trc.getChildPid() << endl << endl;
//memspacy::memory_map::printSystemProcVmap(trc.getChildPid());
//inj.prop_setTraceSyscalls (true);
while (trc.prop_getState () != memspacy::TRCS_STOPPED) {
//if (trc.isSyscall()){
// trc.showSyscall();
//}
//HERE IS WHERE THE DISASSEMBLY takes place
if (trc.readMem(trc.peekReg(a_RIP), inst_buff, MAX_ARCH_INST_LEN)
&& dec.disassemble()) {
dec.printFormatted();
}
trc.singleStep();
}
Issue
The HelloWorld should be comprised of several thousand instructions, but the output I get is this.
mov %rsp, %rdi
add %al, (%rax)
push %rdi
push %rsi
push %rsp
mov %edi, %ebx
in %dx, %al
xor %ecx, -0x3f(%rax)
invalid
Useful facts
It seems that after a couple instructions the read function stops getting any data al all. No error is thrown, the only problem is that reading the memory returns 0 bytes. This would mean that the EOF is reached as per the information in the read() manpage, but lseek() returns a size of 0xFFFFFFFFFFFF, so there should be no problem on that end. Aso, all the reads fall within the mapped regions since I'm using the program counter as the offset.
I can not really think of any thing other than page permissions, but they all have read permissions set, otherwise it wouldn't even execute. The process is properly Ptraced, and the execution runs just fine, with the expected behaviour, even the registers are the exactly the same as in the control test (a test used to check the original behaviour).
My current guess is that at some point it reaches the end of a mapped region and that renders the descriptor useless, hence that "invalid" instruction at the end, but even opening the file on each read the result does not change.
Data
Here is the memory map and the read offset of the last valid read.
00400000-00401000 r-xp 00000000 08:06 7602542 /home/amontes/workspace/memspacy_build/assets/test/test
00600000-00602000 rw-p 00000000 08:06 7602542 /home/amontes/workspace/memspacy_build/assets/test/test
**7fe3eb602000-7fe3eb625000 r-xp 00000000 08:11 657171 /lib/x86_64-linux-gnu/ld-2.19.so**
7fe3eb824000-7fe3eb826000 rw-p 00022000 08:11 657171 /lib/x86_64-linux-gnu/ld-2.19.so
7fe3eb826000-7fe3eb827000 rw-p 00000000 00:00 0
7fff57783000-7fff577a4000 rw-p 00000000 00:00 0 [stack]
7fff577fe000-7fff57800000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Last valid offset 7fe3eb606a7c -> This shows the invalid instruction
First invalid offset 7fe3eb606a7d -> This returns EOF
Any help or any idea would be really appreciated. Thank you.
Well, I don't know if it was a bug caused by some update, or a very specific kernel version or whatever you want to call it. After a clean install of the OS, everything works correctly. I can get the instruction stream, and the the read function always returns data.
Before wiping the HD and prior to the installation, I tried ptrace(PTRACE_PEEKDATA) without luck. Now everything works as it should.
I don't really believe this question is going to help anybody, but sometimes a clean start is the way to go. As much as I hate to admit it, it's happened to me from time to time, not always related to coding software.

Return To Libc with Null byte in the addr

I am trying to perform a return to libc format string attack, but the address I want to write to ( 0x0804a000) has a null byte in it!! I have to read in my format string to snprintf so the null byte causes it to malfunction and Segfaults randomly.
buf[70];
snprintf(buf, 80, argv[1]);
printf(buf);
Here is the GDB dump for printf#plt:
(gdb) disassem 0x080483c0
Dump of assembler code for function printf#plt:
0x080483c0 <+0>: jmp *0x804a000
0x080483c6 <+6>: push $0x0
0x080483cb <+11>: jmp 0x80483b0
End of assembler dump.
Does anyone have any ideas?
My current method is running it like this
./program `perl -e 'print "sh;#\x00\xa0\x04\x08%12345x%10$hn"'`
but there is a null byte. I have also tried
./program `perl -e 'print "sh;#\xff\x9f\x04\x08\x00\xa0\x04\x08%12345x%10$hn%12345x%11$hn"'`
but the address before 0x0804a000 has the global offset table, and therefore snprintf Segfaults before even returning the to function that calls it.
A common way out of this is to make some "memory construction" using the stack.
At the end of the construction you need to have somewhere on the stack (let's call that location n and let's say it correspond to the fifth parameter) :
00 a0 04 08
Given that you can start by writing 0x01 (Or whatever you prefer, we are only interested in the null byte) to n-1. The memory at location n will looks like :
00 ?? ?? ??
Then write 0x04a0 into n+1 thus the memory at location n looks like :
00 a0 04 ??
The final step would be to write 0xff08 into n+3.
Once that's done you can use direct parameter accessing to get your address and write a value at the pointed location.
%12345x%5$n
All you have to do is play with $hn and $n and find a way to overlap the data that suit you. I hope you get the idea.

Resources