Author Topic: How much space to allocate for pointers to structures?  (Read 198 times)

Offline turtle13

  • Jr. Member
  • *
  • Posts: 68
How much space to allocate for pointers to structures?
« on: May 19, 2018, 06:04:07 PM »
I am working with x64 and I have a program that I am disassembling through Ida so that I can outline the stack of a function and understand how much space each arg is taking up on the stack. Note I am using Intel flavor.

I am trying to disassemble the "getpwnam" C function. This function takes in a string (a username) and returns a pointer to the "passwd" structure (in the pwd.h file) for that username.

The structure has the following fields:
char *pw_name (username)
char *pw_passwd (user password)
uid_t pw_uid (user id)
gid_t pw_gid (group id)
char *pw_gecos (user info.)
char *pw_dir (user's home directory)
char *pw_shell (user's shell program)

Here is the segments of code I am trying to deconstruct:

Code: [Select]
call _getpwnam
mov [rbp- 8], rax
cmp [rbp- 8], 0
jz (exit)
mov rax, [rbp- 8]
mov eax, [rax+ 10h]
mov [rbp- 0Ch], eax
mov rax, [rbp- 8]
mov eax, [rax+ 14h]
mov [rbp- 10h], eax
mov rax, [rbp- 8]
mov rax, [rax+ 20h]
mov rdi, rax

This is my interpretation of what's going on:
Code: [Select]
mov rax, [rbp -8] I pass in the username (from rdi register) to getpwnam which returns a pointer to its structure, and the pointer to the structure for that username is stored in rbp- 8 (8 bytes).
The next instruction
Code: [Select]
mov eax, [rax + 10h] takes the value in the rax register + 16 bytes (since rax holds the pointer to the structure, this advances 16 bytes from the beginning of the structure) which is the uid_t pw_uid field (I believe that in 64- bit each char * type is 8 bytes?) and places this 32- bit value in the eax register.
Now we are at
Code: [Select]
mov [rbp- 0Ch], eax which places this 4 byte pw_uid value into the stack at rbp- 10.
Next
Code: [Select]
mov rax, [rbp- 8] puts the pointer to the structure back into rax.
Next
Code: [Select]
mov eax, [rax + 14h] places the value of the beginning of the structure + 20 bytes (gid_t pw_gid) into eax.
Next
Code: [Select]
mov [rbp- 10h], eax transfers the pw_gid value stored in eax onto the stack at rbp- 16.
Next
Code: [Select]
mov rax, [rbp- 8] again places the pointer to the structure into rax.
Next
Code: [Select]
mov rax, [rax + 20h] puts the value of rax + 32 bytes (char *pw_gecos) into rax.
Code: [Select]
mov rdi, rax puts *pw_gecos into rdi...

Am I interpreting this correctly, and where are my missteps?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2303
  • Country: us
Re: How much space to allocate for pointers to structures?
« Reply #1 on: May 19, 2018, 11:12:35 PM »
Hi turtle13,

I will remind you that I don't have much experience with 64-bit code... and that I'm not very good with C. Having said that, your interpretation of what you're looking at seems about right. I would expect pointers - either to the structure or to char - to be 8 bytes. The two numeric values - pid and gid - appear to be 4 bytes. This seems reasonable, at least. If there are errors we're not spotting, they may become obvious when you try to do something with them. Good luck!

Best,
Frank


Offline dreamCoder

  • Jr. Member
  • *
  • Posts: 74
Re: How much space to allocate for pointers to structures?
« Reply #2 on: May 20, 2018, 10:59:51 PM »
@turtle13

Be careful with code re-ordering. C does that all the time for performance reasons, so trying to make sense out of c-generated assembly codes may lead to big confusions.

Offline turtle13

  • Jr. Member
  • *
  • Posts: 68
Re: How much space to allocate for pointers to structures?
« Reply #3 on: May 21, 2018, 09:25:01 PM »
Thanks a lot,
so now, how do you determine what is a "library function" and a "system call?" A syscall should be followed by a "syscall" in x64, correct? A lot of these syscalls have the same name as C lib functions, but when you are looking at disassembly, how to differentiate them? Should I be reviewing manpages for the library functions or for the syscalls?
« Last Edit: May 21, 2018, 11:06:20 PM by turtle13 »

Offline dreamCoder

  • Jr. Member
  • *
  • Posts: 74
Re: How much space to allocate for pointers to structures?
« Reply #4 on: May 21, 2018, 11:14:54 PM »
There's no easy way to do that in Linux assembly. Assembly language in Linux is largely uncharted. You must see everything from C's point of view.

The problem lies in how the kernel services are documented --> it uses C as the main API interface language to describe the kernel binaries (assembly code). They're actually not the C library. They are kernel services/binaries "described" in C language. Two different things here. So one needs to guess each of the data fields, and to make things worse, different distros / kernels / toolchain may use different sizes for the same data field.

However, the total size of a structure can be manually determined by placing some visual markers among the data returned by the kernel. Thats the best approximation you can get if you want to know the size of a kernel's data structure. Here's what I always do if it has to come down to that point;

1. Assign large enough buffer for the structure in question
2. Place some markers (e,g -1 or 0xffffffffffffffff) at the end portion of the buffer
3. Call the kernel. The kernel will then return the data in that buffer.
4. Shrink the size of the buffer until the marker is gone or eaten up.
5. The net difference of data from that marker is the total size of the structure returned by the kernel.
6. Identifying individual data fields from the returned structure is close to impossible. You need to apply some hunch and educated guess. 

Btw, from your first code, I'd say that they have nothing to do with the data structure. With lots of RBP addressings, I say they are local variables on the stack frame, internal to that particular syscall. Logically, the data structure is most likely to be placed in static memory area or heap, and not on the stack. The only thing passed to the stack is probably the pointer to the data structure.

Don't take my words for it. Just sharing my experience dealing with such problems in Linux assembly.


Offline dreamCoder

  • Jr. Member
  • *
  • Posts: 74
Re: How much space to allocate for pointers to structures?
« Reply #5 on: May 22, 2018, 12:58:58 AM »
After "investigating" what "getpwnam" looks like in assembly, here's the summary of the data structure (64-bit Linux);

1. Total size 48 bytes.
2. 7 data members
3. "uidt_xx" and "gidt_xx" are dwords each.
4. All other data members / fields are quadwords pointers
5. There's an undefined data returned (0x400) at the end of the structure. So it is safe to assume that the total size of the structure is 56 bytes. This is in contrast to what's being defined by the "getpwnam(3)" Man which listed only 7 data members. There's actually 8 data members :D

Hope this can shed some lights.