2

I am working in a program using the DWARF and ELF info. I am hooked to another program using a tool called Pin. I have the addresses from the global variables declared in "Y" program and I hook it into my Pin module which I will call "X".

I am getting a bunch of addresses for these global variables. Unfortunately I am having troubles when I try to dereference them. For example (right now I am doing things manually to see if it is doing what is supposed to be doing):

char * limit, * address1;

for(address1 = (char *) 0x804A040, limit = address1 + bytesize; address1 < limit; address1++)
      cout <<  *(address1) << "\n";

I should be getting the variable that is stored in that address which is a char * to a word. Do I have to dereference two pointers in this case? The address and then the char * stored in that address?

This works perfectly fine when I want to dereference an int variable, but whenever I try to dereference a char pointer or variable I get non-ASCII values...

Matt
  • 22,721
  • 17
  • 71
  • 112
attis
  • 171
  • 1
  • 4
  • 16
  • Your `for` statement has only two semicolon-separated arguments, but needs three in order to be valid. – mrb Sep 25 '12 at 20:13
  • Are you expecting to print the address of the string or the string itself? – Pete Fordham Sep 25 '12 at 20:13
  • Are you trying to read data out of the *current process* or a *separate process*? – Adam Rosenfield Sep 25 '12 at 20:17
  • @PeteFordham I am expecting to get the string itself.. What I am getting is literally this: @@� – attis Sep 25 '12 at 20:18
  • I am trying to read data from the process that Pin is hooked up to, so it would be "the current process" controlled by my Pin module @AdamRosenfield – attis Sep 25 '12 at 20:25
  • What is the structure of the data at the address? It sounds like it is supposed to contain an int (how many bytes, 2 or 4 or 8?) along with a pointer to a string. And that the int contains the length of the string. However I am a bit confused by the code snippet. – Richard Chambers Sep 25 '12 at 20:35
  • @RichardChambers I am using the ELF symbol table to get the byte size and addresses of each one of the variables. But right now I am just experimenting with the addresses and seeing if I am able to dereference them without any problems... The structure of the data its a `char *`, more specifically the word `"0xDEADBEEF"` which is a `char array` of `size 10`, at least from my understanding of type sizes – attis Sep 25 '12 at 20:37
  • If it's a char array, and not a pointer to a char array (string), then you would access it as `char *addr = (char *)0x804A040;` `printf("%s\n", addr)`. If it's a pointer to a char array, then you should check my answer. – Toribio Sep 25 '12 at 21:04
  • Try address1 = *((char **)0x804a040) to see if that fixes it. – Benny Smith Jun 12 '13 at 17:58

2 Answers2

7

Think like this: if you want to dereference an int, you use int *:

int *addr = (int *)0x12345678;
printf("%d\n", *addr);

But a string is already a pointer, so if you do this:

char *addr = (char *)0x12345678;

You don't need to dereference it to print it out, so you get it this way:

printf("%s\n", addr);

Additionally, suppose you have this memory:

00000001:  0x12345678
...
12345678:  'A'
12345679:  'B'
1234567A:  '\0'
...

Let's access the address 0x00000001 and see what we can do:

unsigned int *addr = (unsigned int *)0x00000001;

Now *addr holds an integer which is the address of the first character of our string. Functions that take a string argument, usually ask for the string address, that is, a pointer to it, so *addr is also the string we should print on cout or printf for example.

// This should print "AB"
printf("%s\n", (char *)(*addr));

Now if you dereference our value (0x12345678), we'd get the string's first character, and only it, as a char. So if you misuse it and dereference it to a char *, printf would try to search for the memory 'A', which is 0x00000041, and would probably get a segmentation fault.

So, the right way to dereference its value, to get the first character would be this:

// This should print "A"
printf("%c\n", (char)(**addr));

So, as a conclusion, if you are still getting non-ASCII values, that's probably an issue with this kind of hierarchy between addresses, and I would recommend you to strictly debug the memory and see if creating a pointer to a pointer is the right path to your string.

Toribio
  • 3,963
  • 3
  • 34
  • 48
  • I thought this, but I am getting a segmentation fault doing it.. I do have access to that virtual memory space so I don't know why I am getting it.. – attis Sep 25 '12 at 20:24
  • this is really helpful, thanks a lot man! I will try it and let you know what happens!, thanks man @flaviotoribio EDIT: Are you sure that is the correct syntax? The compiler keeps complaining about "invalid type argument of unary *", because of the pointer to a pointer – attis Sep 25 '12 at 21:05
  • Probably, try `(char)(*(char *)*addr)`. That's bacause I used an intermediary variable of another type to do the dereferencing. – Toribio Sep 25 '12 at 21:15
  • I managed to make it work by casting the pointer to a `char *`. `(char *) *(address1)` Thanks a lot man! – attis Sep 25 '12 at 21:33
2

Yes, you need to dereference two pointers. First to get the address of the variable that holds the char*, and then to dereference the char*.

sdkljhdf hda
  • 1,387
  • 9
  • 17