I am trying to write a small program that takes two hard coded character pointers and switches the contents that they point to using an external x86 32bit function located in a .S file. I am using the basic gcc compiler. Here is my C code:
valSwap.c:
#include <stdio.h>
void extern swapMe(char* c, char* d);
int main() {
char* c = "boi";
char* d = "bra";
printf("%s, %s", c, d);
swapMe(c, d);
printf("%s, %s", c, d);
return 0;
}
Before running swapMe(c, d)
the strings that c and d point to are quite clear. After running swapMe(c, d)
I get a Segmentation Fault
. Here is my code for the swapMe external function:
swapMe.S:
.intel_syntax noprefix
.text
.global swapMe
swapMe:
push edi
push esi
mov eax, [esp+4]
mov ecx, [esp+8]
mov edi, [eax]
mov esi, [ecx]
mov [eax], esi
mov [ecx], edi
pop esi
pop edi
ret
Now since swapMe(c, d) is taking in 2 parameters using the cdecl calling convention I should find c and d on the stack at $esp+4
and $esp+8
. I tried to print these values to confirm that they are what I expect. Either they are not what I expected or I tried to print them incorrectly:
(gdb) p/s $esp+4
$1 = (void *) 0xffffdb08
(gdb) x/s $esp+4
0xffffdb08: ""
(gdb) p/s *($esp+4)
Attempt to dereference a generic pointer.
(gdb) x/s *($esp+4)
Attempt to dereference a generic pointer.
I also tried printing $eax as a string since I moved the contents of $esp+4 into $eax.
(gdb) p/x $eax
$3 = 0xf7fa0000
(gdb) x/s $eax
0xf7fa0000: "\260=\033"
(gdb) x/s *$eax
0x1b3db0: <error: Cannot access memory at address 0x1b3db0>
(gdb) x/x $eax
0xf7fa0000: 0xb0
I also printed the hex values of c
and d
before entering swapMe
to see if I'm at least getting the correct value:
(gdb) p &c
$12 = (char **) 0xffffdb2c
(gdb) p c
$16 = 0x565556c0 "boi"
(gdb) p &d
$14 = (char **) 0xffffdb28
(gdb) p d
$15 = 0x565556c4 "bra"
I printed a few others values that may be relevant as well:
30x56555621 <swapMe+2> mov eax,DWORD PTR [esp+0x4] 3
30x56555625 <swapMe+6> mov ecx,DWORD PTR [esp+0x8] 3
>30x56555629 <swapMe+10> mov edi,DWORD PTR [eax] 3
30x5655562b <swapMe+12> mov esi,DWORD PTR [ecx]
(gdb) p/x $eax
$8 = 0xf7fa0000
0x56555621 <swapMe+2> mov eax,DWORD PTR [esp+0x4] 3
30x56555625 <swapMe+6> mov ecx,DWORD PTR [esp+0x8] 3
30x56555629 <swapMe+10> mov edi,DWORD PTR [eax] 3
>30x5655562b <swapMe+12> mov esi,DWORD PTR [ecx] 3
30x5655562d <swapMe+14> mov DWORD PTR [eax],esi 3
30x5655562f <swapMe+16> mov DWORD PTR [ecx],edi
p/x $edi
$11 = 0x1b3db0
30x56555621 <swapMe+2> mov eax,DWORD PTR [esp+0x4] 3
30x56555625 <swapMe+6> mov ecx,DWORD PTR [esp+0x8] 3
30x56555629 <swapMe+10> mov edi,DWORD PTR [eax] 3
30x5655562b <swapMe+12> mov esi,DWORD PTR [ecx] 3
>30x5655562d <swapMe+14> mov DWORD PTR [eax],esi 3
30x5655562f <swapMe+16> mov DWORD PTR [ecx],edi
(gdb) p/x $ecx
$19 = 0x565555f5
(gdb) p/x $esi
$20 = 0x8310c483
I don't understand why I'm getting different values when I print the values of $eax, $edi, $ecx, and $esp
in swapMe
vs when I print the values associated with c
and d
before calling swapMe
. Since swapMe
takes in c
and d
as parameters, I expected to see the same values on the stack when calling swapMe
but I do not. I did not see 0xffffdb2c
or 0x565556c0
once when printing any registers. Please clarify what I did wrong when calling the function, passing in the parameters, or printing the values in the registers. I'm very new to x86 so I probably made a rookie mistake somewhere.