使用 Ollydbg,谁能告诉我变量 "a" 的地址是什么?
Using the Ollydbg,anyone tell me what the address of the variable "a" is?
我非常简单的测试程序
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 12345;
printf("%d\n", a);
system("PAUSE");
return 0;
}
编译连接后,EXE文件为created.Then我在Ollydbg中打开EXE文件:
图中是main()function.But变量的地址我怎么也查不到a
。给printf()
函数传参数的时候,把3039
压栈了,那意思是变量a
的值是3039
?不,值为12345
。那么意思是变量a
的地址是00003039
?任何人
a
变量的地址是 [ebp-8]
。您看到的是 0x3039
赋值,因为十进制 12345
是十六进制 0x3039
。如果您将代码更改为使用十六进制值:int a = 0x12345
,结果会更清楚:
数字常量通常直接编译到代码中。
所以你想知道变量的地址a
.
极其简单:
将此语句插入您的程序。
printf( "address of variable 'a' is: %p\n", &a );
我们如何知道地址?
我们不坐在你的电脑前
并且在大多数计算机上都会有所不同。
使用建议的调用 printf()
来学习 'address'
但是,由于分页、地址转换、虚拟寻址等原因,该地址不是计算机内存中的实际物理地址 space。
像本例中的局部变量 a 存储在堆栈中,因此当函数执行完成时它们可以被丢弃,所以基本上 a 只是位于局部堆栈帧的内存地址。
int a = 12345; // MOV DWORD PTR SS:[EBP-8], 3039
printf("%d\n", a);
在这种情况下,a位于[EBP-8],如果你检查它指向的位置,你可以看到值3039,赋值后当然存储在那里,3039是一个十六进制数,当然是 12345 以 10 为基数。
为了更好地理解这一点,让我们稍微修改一下程序并在 GDB 中对其进行调试。
C:\Codes>gdb test -q
Reading symbols from C:\Codes\test.exe...done.
(gdb) set disassembly-flavor intel
(gdb) list
1 #include<stdio.h>
2
3 int main()
4 {
5 int a = 12345;
6 int b = 0x12345;
7 printf("Variable a %d (decimal) or 0x%x (hex), located at %p or 0x%x\n", a,a,&a,&a);
8 printf("Variable b %d (decimal) or 0x%x (hex), located at %p or 0x%x\n", b,b,&b,&b);
9 return 0;
10 }
(gdb)
标准输出
C:\Codes>test
Variable a 12345 (decimal) or 0x3039 (hex), located at 0022FF4C or 0x22ff4c
Variable b 74565 (decimal) or 0x12345 (hex), located at 0022FF48 or 0x22ff48
可以看到,变量a
和b
的虚拟内存地址实际上分别位于0x22ff4c
和0x22ff48
让我们在GDB中看一下这个程序。
(gdb) break 7
Breakpoint 1 at 0x40135e: file test.c, line 7.
(gdb) run
Starting program: C:\Codes/test.exe
[New Thread 3680.0xed8]
Breakpoint 1, main () at test.c:7
7 printf("Variable a %d (decimal) or 0x%x (hex), located at %p or 0x%x\n", a,a,&a,&a);
(gdb) disassemble
Dump of assembler code for function main:
0x00401340 <+0>: push ebp
0x00401341 <+1>: mov ebp,esp
0x00401343 <+3>: and esp,0xfffffff0
0x00401346 <+6>: sub esp,0x30
0x00401349 <+9>: call 0x401970 <__main>
0x0040134e <+14>: mov DWORD PTR [esp+0x2c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x28],0x12345
=> 0x0040135e <+30>: mov edx,DWORD PTR [esp+0x2c]
0x00401362 <+34>: mov eax,DWORD PTR [esp+0x2c]
0x00401366 <+38>: lea ecx,[esp+0x2c]
0x0040136a <+42>: mov DWORD PTR [esp+0x10],ecx
0x0040136e <+46>: lea ecx,[esp+0x2c]
0x00401372 <+50>: mov DWORD PTR [esp+0xc],ecx
0x00401376 <+54>: mov DWORD PTR [esp+0x8],edx
0x0040137a <+58>: mov DWORD PTR [esp+0x4],eax
0x0040137e <+62>: mov DWORD PTR [esp],0x403024
0x00401385 <+69>: call 0x401be0 <printf>
0x0040138a <+74>: mov edx,DWORD PTR [esp+0x28]
0x0040138e <+78>: mov eax,DWORD PTR [esp+0x28]
0x00401392 <+82>: lea ecx,[esp+0x28]
0x00401396 <+86>: mov DWORD PTR [esp+0x10],ecx
0x0040139a <+90>: lea ecx,[esp+0x28]
0x0040139e <+94>: mov DWORD PTR [esp+0xc],ecx
0x004013a2 <+98>: mov DWORD PTR [esp+0x8],edx
0x004013a6 <+102>: mov DWORD PTR [esp+0x4],eax
0x004013aa <+106>: mov DWORD PTR [esp],0x403064
0x004013b1 <+113>: call 0x401be0 <printf>
0x004013b6 <+118>: mov eax,0x0
0x004013bb <+123>: leave
0x004013bc <+124>: ret
End of assembler dump.
(gdb)
并关注这一行
0x0040134e <+14>: mov DWORD PTR [esp+0x2c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x28],0x12345
从前面的输出可以看出,变量a
和b
的虚拟内存地址实际上位于[esp+0x2c]
或0x22ff4c
和[esp+0x28]
或 0x22ff48
分别。
而
0x3039
& 0x12345
是变量 a
和 b
的十六进制值。
要验证这些变量在GDB中的内存地址,使用print
命令如下:
(gdb) print &a
= (int *) 0x22ff4c
(gdb) print &b
= (int *) 0x22ff48
此外,您可能想知道 0x22ff4c
或 0x22ff48
的地址从何而来。
为了理解这一点,让我们检查一下当前 ESP 寄存器的值
(gdb) info registers esp
esp 0x22ff20 0x22ff20
然后,替换实际的ESP值
[esp+0x2c] = [0x22ff20 + 0x2c] = 0x22ff4c
[esp+0x28] = [0x22ff20 + 0x28] = 0x22ff48
我非常简单的测试程序
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 12345;
printf("%d\n", a);
system("PAUSE");
return 0;
}
编译连接后,EXE文件为created.Then我在Ollydbg中打开EXE文件:
图中是main()function.But变量的地址我怎么也查不到a
。给printf()
函数传参数的时候,把3039
压栈了,那意思是变量a
的值是3039
?不,值为12345
。那么意思是变量a
的地址是00003039
?任何人
a
变量的地址是 [ebp-8]
。您看到的是 0x3039
赋值,因为十进制 12345
是十六进制 0x3039
。如果您将代码更改为使用十六进制值:int a = 0x12345
,结果会更清楚:
数字常量通常直接编译到代码中。
所以你想知道变量的地址a
.
极其简单:
将此语句插入您的程序。
printf( "address of variable 'a' is: %p\n", &a );
我们如何知道地址?
我们不坐在你的电脑前
并且在大多数计算机上都会有所不同。
使用建议的调用 printf()
来学习 'address'
但是,由于分页、地址转换、虚拟寻址等原因,该地址不是计算机内存中的实际物理地址 space。
像本例中的局部变量 a 存储在堆栈中,因此当函数执行完成时它们可以被丢弃,所以基本上 a 只是位于局部堆栈帧的内存地址。
int a = 12345; // MOV DWORD PTR SS:[EBP-8], 3039
printf("%d\n", a);
在这种情况下,a位于[EBP-8],如果你检查它指向的位置,你可以看到值3039,赋值后当然存储在那里,3039是一个十六进制数,当然是 12345 以 10 为基数。
为了更好地理解这一点,让我们稍微修改一下程序并在 GDB 中对其进行调试。
C:\Codes>gdb test -q
Reading symbols from C:\Codes\test.exe...done.
(gdb) set disassembly-flavor intel
(gdb) list
1 #include<stdio.h>
2
3 int main()
4 {
5 int a = 12345;
6 int b = 0x12345;
7 printf("Variable a %d (decimal) or 0x%x (hex), located at %p or 0x%x\n", a,a,&a,&a);
8 printf("Variable b %d (decimal) or 0x%x (hex), located at %p or 0x%x\n", b,b,&b,&b);
9 return 0;
10 }
(gdb)
标准输出
C:\Codes>test
Variable a 12345 (decimal) or 0x3039 (hex), located at 0022FF4C or 0x22ff4c
Variable b 74565 (decimal) or 0x12345 (hex), located at 0022FF48 or 0x22ff48
可以看到,变量a
和b
的虚拟内存地址实际上分别位于0x22ff4c
和0x22ff48
让我们在GDB中看一下这个程序。
(gdb) break 7
Breakpoint 1 at 0x40135e: file test.c, line 7.
(gdb) run
Starting program: C:\Codes/test.exe
[New Thread 3680.0xed8]
Breakpoint 1, main () at test.c:7
7 printf("Variable a %d (decimal) or 0x%x (hex), located at %p or 0x%x\n", a,a,&a,&a);
(gdb) disassemble
Dump of assembler code for function main:
0x00401340 <+0>: push ebp
0x00401341 <+1>: mov ebp,esp
0x00401343 <+3>: and esp,0xfffffff0
0x00401346 <+6>: sub esp,0x30
0x00401349 <+9>: call 0x401970 <__main>
0x0040134e <+14>: mov DWORD PTR [esp+0x2c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x28],0x12345
=> 0x0040135e <+30>: mov edx,DWORD PTR [esp+0x2c]
0x00401362 <+34>: mov eax,DWORD PTR [esp+0x2c]
0x00401366 <+38>: lea ecx,[esp+0x2c]
0x0040136a <+42>: mov DWORD PTR [esp+0x10],ecx
0x0040136e <+46>: lea ecx,[esp+0x2c]
0x00401372 <+50>: mov DWORD PTR [esp+0xc],ecx
0x00401376 <+54>: mov DWORD PTR [esp+0x8],edx
0x0040137a <+58>: mov DWORD PTR [esp+0x4],eax
0x0040137e <+62>: mov DWORD PTR [esp],0x403024
0x00401385 <+69>: call 0x401be0 <printf>
0x0040138a <+74>: mov edx,DWORD PTR [esp+0x28]
0x0040138e <+78>: mov eax,DWORD PTR [esp+0x28]
0x00401392 <+82>: lea ecx,[esp+0x28]
0x00401396 <+86>: mov DWORD PTR [esp+0x10],ecx
0x0040139a <+90>: lea ecx,[esp+0x28]
0x0040139e <+94>: mov DWORD PTR [esp+0xc],ecx
0x004013a2 <+98>: mov DWORD PTR [esp+0x8],edx
0x004013a6 <+102>: mov DWORD PTR [esp+0x4],eax
0x004013aa <+106>: mov DWORD PTR [esp],0x403064
0x004013b1 <+113>: call 0x401be0 <printf>
0x004013b6 <+118>: mov eax,0x0
0x004013bb <+123>: leave
0x004013bc <+124>: ret
End of assembler dump.
(gdb)
并关注这一行
0x0040134e <+14>: mov DWORD PTR [esp+0x2c],0x3039
0x00401356 <+22>: mov DWORD PTR [esp+0x28],0x12345
从前面的输出可以看出,变量a
和b
的虚拟内存地址实际上位于[esp+0x2c]
或0x22ff4c
和[esp+0x28]
或 0x22ff48
分别。
而
0x3039
& 0x12345
是变量 a
和 b
的十六进制值。
要验证这些变量在GDB中的内存地址,使用print
命令如下:
(gdb) print &a
= (int *) 0x22ff4c
(gdb) print &b
= (int *) 0x22ff48
此外,您可能想知道 0x22ff4c
或 0x22ff48
的地址从何而来。
为了理解这一点,让我们检查一下当前 ESP 寄存器的值
(gdb) info registers esp
esp 0x22ff20 0x22ff20
然后,替换实际的ESP值
[esp+0x2c] = [0x22ff20 + 0x2c] = 0x22ff4c
[esp+0x28] = [0x22ff20 + 0x28] = 0x22ff48