IA32寄存器地址 [英] IA32 Register Address

查看:157
本文介绍了IA32寄存器地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有扔我从几个网格化之间的矛盾。我做一个任务,我必须检讨 GDB 组装code,找到正确的输入,使得C程序的工作。为了测试这个,我进入一个测试字符串它由一些数字,并通过步/读大会predict其行为,并找出一个解决方案。

I have a few inter-meshing problems that are throwing me off. I am doing an assignment where I must review assembly code in gdb to find the correct input that makes the C program work. To test this, I enter a test string which consists of some numbers and step through/read the assembly to predict its behavior and figure out a solution.

这里的主要问题:在一个点上,我的整个输入字符串存储在%EAX 注册。当我打电话:

Here's the main problem: at one point, my entire input string is stored in the %eax register. When I call:

x/a $eax

它返回一个十六进制我以为是%EAX 的地址。在这一点上的六角的最后一个字节而变化,这取决于输入。该程序调用与strtol()输入字符串后不久,将删除字符串的第一个号码,缩短字符串放置回%EAX

It returns a hex which I assume to be the address of %eax. At this point last byte of the hex varies, depending on the input. Shortly after the program calls strtol() on the input string, removes the first number from the string, and places the shortened string back into %eax.

这里的事情变得扑朔迷离:貌似不管原始输入有多长或追加输入了多久,当我打电话 X / A $ EAX ,返回的十六进制值的最后一个字节似乎总是等于32。这是一个问题,因为有一个 CMP 测试使用的最后一个字节后不久%EAX 地址,以及32号导致程序崩溃故意

Here's where things get confusing: seemingly no matter how long the original input was or how long the appended input is, when I call x/a on $eax, the last byte of the hex value that is returned seems to always equal 32. This is a problem because there is a cmp test shortly after that uses the last byte of the %eax address, and the number 32 causes the program to crash intentionally.

我误解使用的X / A ,事实上,我返回的十六进制地址不呢?输入的大小可以影响一个注册的地址?任何其他有用的提示,可以帮助我在这种情况呢?

Am I misunderstanding the use of x/a and, in fact, the hex I'm returned is not an address at all? Can the size of an input influence the address of a registry? Any other helpful hints that could help me in this situation?

非常感谢

推荐答案

你的一个评论说:当我打电话 X / S $ EAX ,它返回我的整个在调用之前输入的字符串与strtol()

One of your comments says that "When I call x/s $eax, it returns my entire input string before the call to strtol()".

如果是这种情况,那么%EAX 包含字符串的地址,而 X $ EAX 将尝试显示该地址的内容。

If this is the case, then %eax contains the address of a string, and x $eax will attempt to display the contents of that address.

X / S $ EAX 显示的内容作为一个字符串,所以它会间preT字节在 $ EAX 作为字符,并显示它,因为 $做同样的EAX + 1 ,依此类推,直到遇到终止空。根据您的意见,这正是发生在你 X / S $ EAX 。

x/s $eax displays the contents as a string, so it will interpret the byte at $eax as a character and display it, do the same for $eax + 1, and so on until it encounters the terminating null. According to your comment, this is exactly what happens when you do x/s $eax.

X / $一个EAX 显示地址为另一个地址的内容。换句话说,它会采取前四个字节您的字符串,并显示将有同样的位模式的32位地址。 PTED地址价值这间$ P $是不太可能以任何方式对你有意义。换句话说,它可能看起来像一个地址,但它是极不可能真正成为你的任何程序使用的地址,除了偶然。

x/a $eax displays the contents of that address as another address. In other words, it's going to take the first four bytes of your string, and display the 32 bit address that would have that same bit pattern. This interpreted "address" value is unlikely to be in any way meaningful to you. In other words, it might look like an address, but it's highly unlikely to actually be the address of anything your program uses, except by chance.

如果%EAX 包含指针变量的地址,的然后的运行 X / A 上这将是有意义的,因为那时的另一个地址实际上将被存储在包含在寄存器中的地址。

If %eax contained the address of a pointer variable, then running x/a on it would be meaningful, because then another address actually would be stored at the address contained in that register.

作为演示,考虑这个程序:

As a demonstration, consider this program:

#include <stdio.h>

void myfunc(char * c) {
    char * p = c;
}

int main(void) {
    char * c = "Hello, world!";
    printf("Expected x/a output: 0x");
    for ( size_t i = 8; i > 0; --i ) {
        printf("%X", c[i - 1]);
    }
    printf("\n");
    myfunc(c);
    return 0;
}

在这种特殊情况下,该参数会得到传递给%EAX 寄存器MYFUNC()因此,如果我们打破行的char * p = C; 及运行 X / S $ EAX ,我们应该看你好,世界!显示,因为%EAX 寄存器包含<$ C $的内容C>的char * 变量指向该字符串。

In this particular case, the parameter is going to get passed to myfunc() in the %eax register, so if we break on the line char * p = c; and run x/s $eax, we ought to see "Hello, world!" displayed, because the %eax register contains the contents of the char * variable which points to that string.

如果我们再运行 X / $一个EAX ,因为我在64位计算机有8个字节的地址上运行,我们会得到一个地址这是由ASCII code为'W'(这是 0x77 ),8号人物字符串,其次是ASCII code为(这是 0x20的),第7字字符串,其次是ASCII code为(这是 0x2C )等在一路'H'。在循环的main()计算这个应该是什么样子。它从后到前,因为x86架构是little-endian的。

If we then run x/a $eax, since I'm running this on a 64 bit machine which has 8 byte addresses, we'll get an "address" that is composed of the ASCII code for 'w' (which is 0x77), the 8th character of the string, followed by the ASCII code for ' ' (which is 0x20), the 7th character of the string, followed by the ASCII code for ',' (which is 0x2C), and so on all the way to 'H'. The loop in main() calculates what this should look like. It goes from back to front because the x86 architecture is little-endian.

如果我们运行 X / C-,我们会得到字符串的单个字符。

If we run x/c, we'll get the individual characters of the string.

那么,让我们来看看gdb的输出:

So, let's look at the gdb output:

paul@local:~/src/c/scratch$ gdb ./addr
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/paul/src/c/scratch/addr...done.
(gdb) list
1   #include <stdio.h>
2   
3   void myfunc(char * c) {
4       char * p = c;
5   }
6   
7   int main(void) {
8       char * c = "Hello, world!";
9       printf("Expected x/a output: 0x");
10      for ( size_t i = 8; i > 0; --i ) {
(gdb) break 4
Breakpoint 1 at 0x400604: file addr.c, line 4.
(gdb) run
Starting program: /home/paul/src/c/scratch/addr 
Expected x/a output: 0x77202C6F6C6C6548

Breakpoint 1, myfunc (c=0x40073c "Hello, world!") at addr.c:4
4       char * p = c;
(gdb) x/s $eax
0x40073c:    "Hello, world!"
(gdb) x/a $eax
0x40073c:   0x77202c6f6c6c6548
(gdb) x/c $eax
0x40073c:   72 'H'
(gdb) x/c $eax + 1
0x40073d:   101 'e'
(gdb) x/c $eax + 2
0x40073e:   108 'l'
(gdb)

我们看到我们期待的是什么。

we see exactly what we're expecting.

由于其中的一个例子X / A 实际上是有意义的,让我们改变程序指针传递给一个指针,使所含的地址%EAX (实际上更改为%RAX 在这里,因为我是一个64位系统上,并需要完整的8字节寄存器持有堆栈变量,这将是相当高的地址 - 第一个例子,我经过静态分配的字符串地址你好,世界! ,这是保存在足够低的地址,很容易融入的4个字节的一部分%RAX 注册即%EAX 在x64处理器)确实点到另一个地址:

As an example of where x/a would actually make sense, let's change the program to pass a pointer to a pointer, so that the address contained in %eax (actually changed to %rax here, since I'm on a 64 bit system, and need the full 8 byte register to hold the address of a stack variable, which will be quite high - in the first example, I was passing the address of the statically allocated string literal "Hello, world!", which was stored at a low enough address to easily fit into the 4-byte part of the %rax register which is %eax on an x64 processor) really does point to another address:

#include <stdio.h>

void myfunc(char ** c) {
    char ** p = c;
}

int main(void) {
    char * c = "Hello, world!";
    printf("Contents of c, and expected x/a output: %p\n", (void *)c);
    myfunc(&c);
    return 0;
}

和gdb的输出此时:

paul@thoth:~/src/c/scratch$ gdb ./addr2
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/paul/src/c/scratch/addr2...done.
(gdb) list
1   #include <stdio.h>
2   
3   void myfunc(char ** c) {
4       char ** p = c;
5   }
6   
7   int main(void) {
8       char * c = "Hello, world!";
9       printf("Contents of c, and expected x/a output: %p\n", (void *)c);
10      myfunc(&c);
(gdb) break 4
Breakpoint 1 at 0x4005b4: file addr2.c, line 4.
(gdb) run
Starting program: /home/paul/src/c/scratch/addr2 
Contents of c, and expected x/a output: 0x4006b0

Breakpoint 1, myfunc (c=0x7fffffffe478) at addr2.c:4
4       char ** p = c;
(gdb) x/a $rax
0x7fffffffe478: 0x4006b0
(gdb) 

这里,参数 - 因此%RAX 注册 - 包含的char * C 中的地址的main() C 包含的地址你好,世界!字符串。因此,当我们显示包含在%RAX 作为地址的地址的内容,我们得到的的地址你好,世界!字符串,它上面的第一个例子不同,实际上是一个有意义的地址。

Here, the parameter - and therefore the %rax register - contains the address of char * c in main(), and c contains the address of the "Hello, world!" string. So when we display the contents of the address contained in %rax as an address, we get the address of the "Hello, world!" string, which unlike the first example above, actually is a meaningful address.

这篇关于IA32寄存器地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆