static int func_name (const uint8_t * address)
{
int result;
asm ("movl $1f, %0; movzbl %1, %0; 1:"
: "=&a" (result) : "m" (*address));
return result;
}
I have gone through inline assembly references over internet.
But i am unable to figure out what this code is doing, eg. what is $1f ?
And what does "m" means? Isn't the normal inline convention to use "=r" and "r" ?
The code is functionally identical to return *address but not absolutely equivalent to this wrt. to the generated binary / object file.
In ELF, the usage of the forward reference (i.e. the mov $1f, ... to retrieve the address of the assembly local label) results in the creation of what's called a relocation. A relocation is an instruction to the linker (either at executable creation or later to the dynamic linker at executable/library loading) to insert a value only known at link/load time. In the object code, this looks like:
Disassembly of section .text:
0000000000000000 :
0: b8 00 00 00 00 mov $0x0,%eax
5: 0f b6 07 movzbl (%rdi),%eax
8: c3 retq
Notice the value (at offset 1 into the .text section) is zero here even though that's actually not correct - it depends on where in the running code the function will end up. Only the (dynamic) linker can ultimately know this, and the information that this piece of memory needs to be updated as it is loaded is actually placed into the object file:
$ readelf -a xqf.o
ELF Header:
[ ... ]
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000000009 0000000000000000 AX 0 0 16
[ 2] .rela.text RELA 0000000000000000 000004e0
0000000000000018 0000000000000018 10 1 8
[ ... ]
Relocation section '.rela.text' at offset 0x4e0 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000001 00020000000a R_X86_64_32 0000000000000000 .text + 8
[ ... ]
This ELF section entry says:
look at offset 1 into the .text section
there's a 32bit value that will be zero-extended to 64-bit (R_X86_64_32). This may have been intended for use in 32-bit code, but in a 64-bit non-PIE executable that's still the most efficient way to put an address into a register; smaller than lea 1f(%rip), %0 for a R_X86_64_PC32 RIP-relative relocation. And yes a RIP-relative LEA into a 32-bit register is legal, and saves a byte of machine code if you don't care about truncating the address.
the value you (as the linker) need to put there is that of .text + 8 (which will have to be computed at link / load time)
This entry is created thanks to the mov $1f, %0 instruction. If you leave that out (or just write return *address), it won't be there.
I've forced code generation for the above by removing the static qualifier; without doing so, a simple compile actually creates no code at all (static code gets eliminated if not used, and, a lot of the time, inlined if used).
Due to the fact that the function is static, as said, it'll normally be inlined at the call site by the compiler. The information where it's used therefore usually gets lost, as does the ability of a debugger to instrument it. But the trick shown here can recover this (indirectly), because there will be one relocation entry created per use of the function. In addition to that, methods like this can be used to establish instrumentation points within the binary; insert well-known/strictly-defined but functionally-meaningless small assembly statements at locations recoverable through the object file format, and then let e.g. the debugger / tracing utilities replace them with "more useful" things when needed.
$1f is the address of the 1 label. The f specifies to look for the first label named 1 in the forward direction. "m" is an input operand that is in memory. "=&a" is an output operand that uses the eax register. a specifies the register to use, = makes it an output operand, and & guarantees that other operands will not share the same register.
Here, %0 will be replaced with the first operand (the eax register) and %1 by the second operand (The address pointed to by address).
All these and more are explained in the GCC documentation on Inline assembly and asm contraints.
This piece of code (apart from being non-compilable due to two typos) is hardly useful.
This is what it turns into (use the -S switch):
_func_name:
movl 4(%esp), %edx ; edx = the "address" parameter
movl $1f, %eax ; eax = the address of the "1" label
movzbl (%edx), %eax; eax = byte from address in edx, IOW, "*address"
1:
ret
So the entire body of the function can be replaced with just
return *address;
This is a code snippet from the PintOS project.
The function here is used by the OS kernel to read a byte at address from the user address space. That is done by movzbl %1, %0 where 0% is result and 1% is address. But before that, the kernel has to move the address of $1f(which is the address of the instruction right after movzbl %1, %0) to the eax register. This move seems useless because some context information is missing. The kernel does that for the page fault interrupt handler to use it. Because address could be an invalid one offered by the user, and it might cause a page fault. When that happened, the interrupt handler would take over, set eip equal to eax(which is the memory address of $1f), and also set eax to -1 to indicate that the read failed. After that, the kernel was able to return from the handler to $1f and move on. Without saving the address of $1f, the handler would have no idea where it should return to, and could only go back to movzbl %1, %0 again and again.
Related
How to pass a variable from a C program to a assembly function.
Example:
main.c:
void main() {
unsigned int passthis = 42
extern asm_function();
asm_function(passthis)
}
main.asm:
bits 32
global start
section .text
asm_function:
...
How do I access passthis within asm_function.
Edit: Probably should've mentioned i'm not using a OS, i'm compiling using a i686-elf cross compiler and am going to use it as a kernel.
If you compile your C into 32-bit code with the default GCC options (not -mregparm=3 like the Linux kernel uses), then on function entry the first argument is on the stack just above the return address (at [esp+4]), but that offset changes after you push anything or move ESP around.
You can use [ebp+8] after setting up a traditional stack pointer (which doesn't change during the function even when ESP does).
For example, int asm_function(int) can be implemented as:
;bits 32 ; unneeded, nasm -felf32 implies this.
global asm_function ; include asm_function in ELF .o symbol table for linking
section .text
asm_function:
push ebp
mov ebp, esp
mov eax, [ebp+8] ; return the first argument
mov esp, ebp
pop ebp
ret
For each parameter after this, just simply add another 4 (i.e. for the 2nd parameter, use [ebp+12]). As you can see, setting up EBP as a frame pointer adds a lot of overhead for tiny functions.
Some non-ELF systems/ABIs prepend a leading underscore to C symbol names, so you should declare both asm_function and _asm_function for your code to be roughly equivalent across these ABIs, like so:
global _asm_function
global asm_function ; make both names of the function global
section .text
_asm_function:
asm_function: ; make both symbols point to the same place
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov esp, ebp
pop ebp
ret
x86 has probably a handful of different calling conventions. It depends on a number of things, like windows vs. linux, and on what compiler environment you're using, 32-bit vs. 64-bit, etc..
Best probably to look at the output of the compiler you're using to see how the parameter is being passed, and do the corresponding appropriate way of accepting the parameter in your assembly. So if it is pushed on the stack then expect it there, if it is passed in a register, expect it there...
You can look at the output using a disassembler, or using a debugger.
I am currently learning on buffer overflow attacks.
I understand that the idea is to overwrite the return address.
The return address points to the statement that follows the function call. What I am wondering: Does this pointer point to the text segment of the program? Or does it point to the heap or something else?
Thanks a lot for your help!
Since you're referring to return addresses on the stack, I'm going to assume that you're on the ubiquitous x86_64. You can examine this yourself by replacing the call instruction with its equivalent push, jmp, and label (assuming myfn is a leaf routine):
push offset RA1
jmp _myfn
RA1:
; Remainder of instructions in the calling code...
When I actually assemble this I get the following code:
00401004: 68 0B 10 40 00 push 40100Bh ; RA1
00401009: EB F5 jmp 00401000 ; myfn
0040100B: 33 C0 xor eax,eax ; next instruction
Now, 00400000 is the default base address for executables on the MS Windows PE format, and for this particular executable of mine, it says that the .text (i.e. code) section runs from 00401000 to 0040100D, so yes, the return address in [esp] when myfn is called indeed points within the .text segment.
Where else did you think it might point? The return address has to be to the address of the instruction immediately after the call instruction, which, like all other code, goes in the .text segment.
I'm writing a simple program that converts brainfuck code into x86_64 assembly. Part of that involves creating a large zero-initialized array at the beginning of the program. Thus, each compiled program starts with the following assembly code:
.data
ARR:
.space 32430
.text
.globl _start
.type _start, #function
_start:
... #code as compiled from the brainfuck program
...
From there the compiled program is supposed to be able to access any part of that array, but it should segfault if it tries to access memory before or after it.
Because the array is followed directly by a .text section, which by my understanding is read only, and because it is the first section of the program, I expected that my desired behavior would follow naturally. Unfortunately, this is not the case: compiled programs are able to access non-zero initialized data to the left of (that is, at lower addresses than) the beginning of the array.
Why is this the case and is there anything I can include in the assembly code that would prevent it?
This is, of course, highly system-dependent, but since your observations suit a typical Linux/GNU system, I'll refer to such a system.
what I assume is that the linker isn't putting my segments where I think it is.
True, the linker puts the segments not in the order they appear in your code snippet, but rather .text first, .data second. We can see this e. g. with
> objdump -h ARR
ARR: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000042 08048074 08048074 00000074 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00007eae 080490b8 080490b8 000000b8 2**2
CONTENTS, ALLOC, LOAD, DATA
compiled programs are able to access non-zero initialized data to the left of (that is, at lower addresses than) the beginning of the array.
Why is this the case …
As we also see in the above example, the .data section is linked at memory address 080490b8. Although memory pages have the length PAGE_SIZE (here getconf PAGE_SIZE yields 4096, i. e. 100016) and start at multiples of that size, the data starts at an address offset equal to the file offset 000000b8 (where the data is stored in the disk file), because the file pages containing the .data section are mapped into memory as copy-on-write pages. The non-zero initialized data below the .data section is just what happens to be in the first file page at bytes 0 to b716, including .text.
… is there anything I can include in the assembly code that would prevent it?
I'd prefer a solution that places my segments such that a bad array access causes a segfault.
As Margaret Bloom and Ped7g hinted at, you could allocate additional data below ARR and create an inaccessible guard page. This can be achieved with minimal effort by aligning ARR to the next page address. The example program below implements this and allows to test it by accepting an index argument (optionally negative) with which the ARR data is accessed; if within bounds, it should exit with status 0, otherwise segfault. Note: This method works only if the .text section does not end at a page boundary, because if it does, the .align 4096 is without effect; but since the assembly code is created with a converter program, that program should be able to check this and add a few extra .text bytes if needed.
.data
.align 4096
ARR:
.space 30000 # we'll actually get 32768
.text
.globl _start
.type _start, #function
_start:
mov (%esp),%ebx # argc
cmp $1,%ebx
jbe 9f
mov $0,%ax
mov $1,%ebx # sign 1
mov 8(%esp),%esi # argv[1]
0: movb (%esi),%cl # convert argument string to integer
jcxz 1f
sub $'0',%cl
js 2f
mov $10,%dx
mul %dx
add %cx,%ax
jmp 3f
2: neg %ebx # change sign
3: add $1,%esi
jmp 0b
1: mul %ebx # multiply with sign 1 or -1
movzx ARR(%eax),%ebx# load ARR[atoi(argv[1])]
9: mov $1,%eax
int $128 # _exit(ebx);
In the following code segment:
int func()
{
int a=7;
return a;
}
Is the code segment where the value 7 is stored in the executable? Or is it in data segment or in the code segment? Will the answer depends on the Operating system or the compiler?
Each executable format has some sections. One of them is text, contains the assembly - binary code. One of them is heap where malloc-ed data is found and on is stack where local variables are stored. There are several others but it doesn't matter now. The above three are common everywhere.
Now, local data like your a resides on the stack. In the executable file, the value is stored in the text section.
I've added a main to your code (returning 0), compiled with -g then did objdump -CDgS a.out and searched for 0x424242 (I've replaced your 7 with a value with lesser chance of randomly occurring in code).
00000000004004ec <func>:
int func()
{
4004ec: 55 push %rbp
4004ed: 48 89 e5 mov %rsp,%rbp
int a=0x42424242;
4004f0: c7 45 fc 42 42 42 42 movl $0x42424242,-0x4(%rbp)
return a;
4004f7: 8b 45 fc mov -0x4(%rbp),%eax
}
4004fa: 5d pop %rbp
4004fb: c3 retq
As you see, c7 45 fc 42 42 42 42 means that the value is stored in the generated file. Indeed, this is the case when looking at the binary via xxd:
$ xxd a.out | grep 4242
00004f0: c745 fc42 4242 428b 45fc 5dc3 5548 89e5 .E.BBBB.E.].UH..
You can recognize the above assembly line in the xxd snippet.
Since a is implicitly auto (i.e. is not extern or static) it is stored in the call stack frame.
In fact, the compiler may optimize that: probably, in your case, when optimizing, it will stay in a register (or be constant propagated and constant folded): no need to allocate a call stack slot for your a
This is of course compiler, target platform, and operating system dependent. For the GCC compiler, understand the Gimple internal representation (thru -fdump-tree-all, or using the MELT probe) and look at the generated assembler code (use -fverbose-asm -S -O)
See also this answer which gives a lot of references.
GCC 4.8 on Linux/x86-64 compiles (with gcc -S -fverbose-asm -O) your function into:
.globl func
.type func, #function
func:
.LFB0:
.cfi_startproc
movl $7, %eax #,
ret
.cfi_endproc
.LFE0:
.size func, .-func
So you see that in your particular case no additional space is used for 7, it is directly stored in%eax which is the register (defined in the ABI conventions) to hold its returned result.
The value 7 is stored in the machine code, inside the movl machine instruction. When func is executed, that 7 is loaded into register %eax containing the returned result of func.
Depending on the example code, variable "a" goes in call stack, place to store local variables along with function call information like program counter, return addr etc
I am looking into assembly code generated by GCC. But I don't understand:
movl $0x2d, 0x4(%esp)
In the second operand, what does 0x4 stands for? offset address? And what the use of register EAX?
movl $0x2d, 0x4(%esp) means to take the current value of the stack pointer (%esp), add 4 (0x4) then store the long (32-bit) value 0x2d into that location.
The eax register is one of the general purpose 32-bit registers. x86 architecture specifies the following 32-bit registers:
eax Accumulator Register
ebx Base Register
ecx Counter Register
edx Data Register
esi Source Index
edi Destination Index
ebp Base Pointer
esp Stack Pointer
and the names and purposes of some of then harken back to the days of the Intel 8080.
This page gives a good overview on the Intel-type registers. The first four of those in the above list can also be accessed as a 16-bit or two 8-bit values as well. For example:
3322222222221111111111
10987654321098765432109876543210
<- eax ->
<- ax ->
<- ah -><- al ->
The pointer and index registers do not allow use of 8-bit parts but you can have, for example, the 16-bit bp.
0x4(%esp) means *(%esp + 4) where * mean dereferencing.
The statement means store the immediate value 0x2d into some local variable occupying the 4th offset on the stack.
(The code you've shown is in AT&T syntax. In Intel syntax it would be mov [esp, 4], 2dh)
0x4 in the second operand is an offset from the value of the register in the parens. EAX is a general purpose register used for assembly coding (computations, storing temporary values, etc.) formally it's called "Accumulator register" but that's more historic than relevant.
You can read this page about the x86 architecture. Most relevant to your question are the sections on Addressing modes and General purpose registers
GCC assembly operands follow a byte (b), word (w), long (l) and so on such as :
movb
movw
movl
Registers are prefixed with a percentage sign (%).
Constants are prefixed with a dollar sign ($).
In the above example in your question that means the 4th offset from the stack pointer (esp).
Hope this helps,
Best regards,
Tom.
You're accessing something four bytes removed from where the stack pointer resides. In GCC this indicates a parameter (I think -- positive offset is parameters and negative is local variables if I remember correctly). You're writing, in other words, the value 0x2D into a parameter. If you gave more context I could probably tell you what was going on in the whole procedure.