Getting stdout pointer in assembly - c

I want to call c function 'fputc', so that I need FILE pointer (in my case it's stdout). I know that I can use putc equivalent, but I'm curious if it is even possible to get pointer to stdout in asm. In c or c++ I would write something like 'stdout' or '&_iob[1]'. Is it even possible to get this working without replacing 'fputc' with 'putc'? (Target architecture is Windows on x86-32).
Example code (I want to print 'A'):
push <the value I need>
push 0x41
call _fputc
add esp, 8

You call __iob_func from MSVCRT.dll, it returns the iob struct and you add 0x30 to it and that's the address for stdout.

Related

I have a trouble with looking into the read() function code defined in <unistd.h>

I am now trying to understand how read(2) function works by looking into the actual code implementation and first, I try to see how it is defined in #include header file.
In that file, I found this :
ssize_t read(int, void *, size_t) __DARWIN_ALIAS_C(read);
And then, I googled to find the actual read() function declaration.
And,
https://github.com/lattera/glibc/blob/master/io/read.c
I found this. In this code,
/* Read NBYTES into BUF from FD. Return the number read or -1. */
ssize_t
__libc_read (int fd, void *buf, size_t nbytes)
{
if (nbytes == 0)
return 0;
if (fd < 0)
{
__set_errno (EBADF);
return -1;
}
if (buf == NULL)
{
__set_errno (EINVAL);
return -1;
}
__set_errno (ENOSYS);
return -1;
}
And here is my questions now.
what is __libc_ before read ?
why is it needed? And when user calls read(2), how this function can be called?
The way I see it, this code has nothing to do with reading the buffer from file descriptor, rather it has only the code dealing with the possible errors : fd < 0 or buff is NULL , etc.
So, where is the code actually implement the actual function of read(2) function?
Am I look and found in the wrong way or source?
read (and, traditionally, all of the functions defined in "section 2" of the Unix manual -- that's what that (2) means) is a system call. That means most of the work is done by the operating system kernel, not by code in your own process. The C library only contains a system-call wrapper that executes a special instruction that transfers control to the kernel.
The code you found is a placeholder, not a system-call wrapper. As you surmised, it doesn't actually implement read. It would only ever be used temporarily, in an incomplete port to an operating system that doesn't have a system call named read. None of the complete ports in the C library you are looking at actually use that code. They instead use a real system-call wrapper. This C library automatically generates system-call wrappers at build time, so I can't link to actual code, but I can show you an example of what the generated code for a system-call wrapper might look like. (Note: this is NOT the actual code used on any operating system I am familiar with. I deliberately removed some complications.)
.text
.globl read
.type read, #function
read:
movl $SYS_read, %eax
syscall
testq %rax
js .error
ret
.error:
negl %eax
movq errno#gottpoff(%rip), %rdx
movl %eax, %fs:(%rdx)
movq $-1, %rax
ret
I wrote this example in x86 assembly language on purpose, because there's no way to get the special syscall instruction from plain C. Some C libraries use an "assembly insert" extension for the syscall instruction and write the rest of the wrapper in C, but for what you're trying to understand, the assembly language is what you should think about.
Inside the kernel, there's a special "trap handler" that receives control from the syscall instruction. It looks at the value in %eax, sees that it is the system call number SYS_read (the actual numeric value may vary from OS to OS), and calls the code that actually implements the read operation.
After the system call returns, the wrapper tests whether it returned a negative number. If so, that indicates an error. (Note: this is one of the places where I removed some complications.) It flips the sign of that number, copies it into errno (which is more complicated than just mov %eax, errno because errno is a thread-local variable), and returns −1. Otherwise the value returned is the number of bytes read and it returns that directly.
The other answer links to an implementation of read but unfortunately it's from an OS kernel that's popular but complicated and difficult to understand. And I regret to say I don't have a better teaching example to point you at.
The __libc_ prefix on the read placeholder implementation is there because there are actually three different names for read in this C library: read, __read, and __libc_read. As the other answer points out, there's some special macros below the code you quoted that arrange for them all to be names for the same function. The auto-generated real system-call wrapper for read will also have all of those names.
This is a hack to achieve "namespace cleanliness", which you only need to worry about if you ever set out to implement a full-fledged and fully standards compliant C library. The short version is that there are many functions in the C library that need to call read, but they cannot use the name read to call it, because a C program is technically allowed to define a function named read itself.
Incidentally, you need to take care to look at headers and implementation code belonging to the same C library. You appear to have the unistd.h from MacOS on your computer, but the read code you found belongs to the GNU C Library, which is a completely different implementation. The basic declaration of read,
ssize_t read(int, void *, size_t);
is specified by the POSIX standard, so it will be the same in both, but the __DARWIN thing after that is a quirk of the MacOS C library. The GNU library has a declaration with different quirks:
extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur;
You are missing the important part of the posted code.
weak_alias (__libc_read, __read)
weak_alias (__libc_read, read)
It does not matter what prefix is used. This function __libc_read is used as a stub function of the system call read. If the linker does not find the system call read than the stub is used, that will return the error code ENOSYS.
Since read is the system call, you should search its implementation in the OS source files. The implementation depends on the file descriptor used. For example if read is called in Linux for the filesystem, the code of read is here: http://lxr.linux.no/linux+v4.15.14/fs/read_write.c#L566

GCC Inline-Assembly Error: "Operand size mismatch for 'int'"

first, if somebody knows a function of the Standard C Library, that prints
a string without looking for a binary zero, but requires the number of characters to draw, please tell me!
Otherwise, I have this problem:
void printStringWithLength(char *str_ptr, int n_chars){
asm("mov 4, %rax");//Function number (write)
asm("mov 1, %rbx");//File descriptor (stdout)
asm("mov $str_ptr, %rcx");
asm("mov $n_chars, %rdx");
asm("int 0x80");
return;
}
GCC tells the following error to the "int" instruction:
"Error: operand size mismatch for 'int'"
Can somebody tell me the issue?
There are a number of issues with your code. Let me go over them step by step.
First of all, the int $0x80 system call interface is for 32 bit code only. You should not use it in 64 bit code as it only accepts 32 bit arguments. In 64 bit code, use the syscall interface. The system calls are similar but some numbers are different.
Second, in AT&T assembly syntax, immediates must be prefixed with a dollar sign. So it's mov $4, %rax, not mov 4, %rax. The latter would attempt to move the content of address 4 to rax which is clearly not what you want.
Third, you can't just refer to the names of automatic variables in inline assembly. You have to tell the compiler what variables you want to use using extended assembly if you need any. For example, in your code, you could do:
asm volatile("mov $4, %%eax; mov $1, %%edi; mov %0, %%esi; mov %2, %%edx; syscall"
:: "r"(str_ptr), "r"(n_chars) : "rdi", "rsi", "rdx", "rax", "memory");
Fourth, gcc is an optimizing compiler. By default it assumes that inline assembly statements are like pure functions, that the outputs are a pure function of the explicit inputs. If the output(s) are unused, the asm statement can be optimized away, or hoisted out of loops if run with the same inputs.
But a system call like write has a side-effect you need the compiler to keep, so it's not pure. You need the asm statement to run the same number of times and in the same order as the C abstract machine would. asm volatile will make this happen. (An asm statement with no outputs is implicitly volatile, but it's good practice to make it explicit when the side effect is the main purpose of the asm statement. Plus, we do want to use an output operand to tell the compiler that RAX is modified, as well as being an input, which we couldn't do with a clobber.)
You do always need to accurately describe your asm's inputs, outputs, and clobbers to the compiler using Extended inline assembly syntax. Otherwise you'll step on the compiler's toes (it assumes registers are unchanged unless they're outputs or clobbers). (Related: How can I indicate that the memory *pointed* to by an inline ASM argument may be used? shows that a pointer input operand alone does not imply that the pointed-to memory is also an input. Use a dummy "m" input or a "memory" clobber to force all reachable memory to be in sync.)
You should simplify your code by not writing your own mov instructions to put data into registers but rather letting the compiler do this. For example, your assembly becomes:
ssize_t retval;
asm volatile ("syscall" // note only 1 instruction in the template
: "=a"(retval) // RAX gets the return value
: "a"(SYS_write), "D"(STDOUT_FILENO), "S"(str_ptr), "d"(n_chars)
: "memory", "rcx", "r11" // syscall destroys RCX and R11
);
where SYS_WRITE is defined in <sys/syscall.h> and STDOUT_FILENO in <stdio.h>. I am not going to explain all the details of extended inline assembly to you. Using inline assembly in general is usually a bad idea. Read the documentation if you are interested. (https://stackoverflow.com/tags/inline-assembly/info)
Fifth, you should avoid using inline assembly when you can. For example, to do system calls, use the syscall function from unistd.h:
syscall(SYS_write, STDOUT_FILENO, str_ptr, (size_t)n_chars);
This does the right thing. But it doesn't inline into your code, so use wrapper macros from MUSL for example if you want to really inline a syscall instead of calling a libc function.
Sixth, always check if the system call you want to call is already available in the C standard library. In this case, it is, so you should just write
write(STDOUT_FILENO, str_ptr, n_chars);
and avoid all of this altogether.
Seventh, if you prefer to use stdio, use fwrite instead:
fwrite(str_ptr, 1, n_chars, stdout);
There are so many things wrong with your code (and so little reason to use inline asm for it) that it's not worth trying to actually correct all of them. Instead, use the write(2) system call the normal way, via the POSIX function / libc wrapper as documented in the man page, or use ISO C <stdio.h> fwrite(3).
#include <unistd.h>
static inline
void printStringWithLength(const char *str_ptr, int n_chars){
write(1, str_ptr, n_chars);
// TODO: check error return value
}
Why your code doesn't assemble:
In AT&T syntax, immediates always need a $ decorator. Your code will assemble if you use asm("int $0x80").
The assembler is complaining about 0x80, which is a memory reference to the absolute address 0x80. There is no form of int that takes the interrupt vector as anything other than an immediate. I'm not sure exactly why it complains about the size, since memory references don't have an implied size in AT&T syntax.
That will get it to assemble, at which point you'll get linker errors:
In function `printStringWithLength':
5 : <source>:5: undefined reference to `str_ptr'
6 : <source>:6: undefined reference to `n_chars'
collect2: error: ld returned 1 exit status
(from the Godbolt compiler explorer)
mov $str_ptr, %rcx
means to mov-immediate the address of the symbol str_ptr into %rcx. In AT&T syntax, you don't have to declare external symbols before using them, so unknown names are assumed to be global / static labels. If you had a global variable called str_ptr, that instruction would reference its address (which is a link-time constant, so can be used as an immediate).
As other have said, this is completely the wrong way to go about things with GNU C inline asm. See the inline-assembly tag wiki for more links to guides.
Also, you're using the wrong ABI. int $0x80 is the x86 32-bit system call ABI, so it doesn't work with 64-bit pointers. What are the calling conventions for UNIX & Linux system calls on x86-64
See also the x86 tag wiki.

What does `PUSH 0xFFFFFFFF` mean in a function prologue?

I'm trying to understand assembly code through a book called "Reverse Engineering for Beginners" [LINK]. There was a piece of code win-32 assembly code I didn't quite understand.
main:
push 0xFFFFFFFF
call MessageBeep
xor eax,eax
retn
What does the first PUSH instruction do?? Why is it pushing 0xFFFFFFFF to the stack, but never popping it back again? What is the significance of 0xFFFFFFFF?
Thanks in advance.
You are looking at the equivalent code for
int main() {
MessageBeep(0xffffffff);
return 0;
}
The assembly code actually don't contain any prolongue or epilogue, since this function doesn't make use of the stack or clobber any preserved register, it just has to perform a function call and return 0 (which is put in eax at the end). It may be receiving arguments it doesn't use as long as it uses the cdecl calling convention (where the caller is responsible for arguments cleanup).
MessageBeep, as almost all Win32 APIs, uses the stdcall calling convention (you'll find it in the C declarations hidden behind the WINAPI macro), which means that it's the called function who is responsible for the cleaning up of the stack from the parameters.
Your code pushes 0xFFFFFFFF as the only argument to MessageBeep, and calls it. MessageBeep does his things, and at the end ensures that all its arguments are popped from the stack before returning (actually, there's a special form of the ret instruction for this). When your code regains control, the stack is as before you pushed the arguments.

Passing a function and its size to WriteFile

As a learning exercise, I'm writing a program that outputs a DLL at run-time.
I've written the PE header and have successfully written the DOS header, NT header, optional section header and the .text section header to a file using WriteFile, e.g.:
WriteFile(hFile, &nt_header, sizeof(nt_header), &written, NULL);
I'm now like to add some code to the .text section, but I don't know how to pass a function and its size to WriteFile, e.g.:
static int test(void)
{
return 10;
}
WriteFile's second parameter has type LPCVOID. I tried passing in test, but that only wrote 1 byte. Passing a pointer to test wrote 4 bytes, as expected.
This is probably obvious, but I'm not understanding where I'm going wrong.
It's obvious, but the answer isn't what you want, probably. It can't be done, at least not portably.
Functions in C don't have sizes. You also can't assume that the concept "address of a function" means "address of the first machine instruction in the compiled code for a function".
In short, what you're doing isn't possible at that level in C, you can't do I/O on functions directly.

Assembly analyzing system() function called in C

So I made a very simple C program to study how C works on the inside. It has just 1 line in the main() excluding return 0:
system("cls");
If I use ollydebugger to analyze this program It will show something like this(text after the semicolons are comments generated by ollydebugger.
MOV DWORD PTR SS:[ESP],test_1.004030EC ; ||ASCII "cls"
CALL <JMP.&msvcrt.system> ; |\system
Can someone explain what this means, and if I want to change the "cls" called in the system() to another command, where is the "cls" stored? And how do I modify it?
You are using 32 bit Windows system, with its corresponding ABI (the assumptions used when functions are called).
MOV DWORD PTR SS:[ESP],test_1.004030EC
Is equivalent to a push 4030ech instruction, that simply store the address of the string cls on the stack.
This is the way parameters are passed to functions and tell us that the string cls is at address 4030ech.
CALL <JMP.&msvcrt.system> ; |\system
This is the call to the system function from the CRT.
The JMP in the name is due how linking works by default with Visual Studio compilers and linkers.
So those two lines are simply passing the address of the string to the system function.
If you want do modify it you need to check if it is in a writable section (I think is not) by checking the PE Sections, your debugger may have a tool for that. Or you could just try anyway the following:
Inspect the memory at 4030ech, you will see the string, try editing it (this is debugger dependent).
Note: I use the TASM notation for hex numbers, i.e. 123h means 0x123 in C notation.

Resources