通过下标运算取任何地址
取 p[2] 的地址
定义 int *p = NULL,求 p[2] 的地址,编写程序。
#include #include int main(){ int *p = NULL; printf("%08x\r\n", &p[2]); system("pause"); return 0;}
由公众号数组这篇文章的计算公式:ary[n] 的地址是(int)ary + sizeof(type)*n。运用公式必须有两个操作数,一个操作数必须是某类型的地址,另一个操作数必须为整形类。取出某类型的地址代入到公式 ary 部分,取出整形代入到上述公式中 n 部分,取出数组元素的类型代入到上述公式中 type 部分。
因为 p 是 int 类型的地址,p 的值是 0 。2 是整形,数组元素的类型是 int,所以 &p[2] = (int)p + sizeof(int)*2 = 0 + 4*2 = 8,所以打印出来的值为 00000008。
取地址 0x00400000 处的四个字节内容
由公式,ary[n] 的地址是(int)ary + sizeof(type)*n,所以可以推出
0x00400000 = (int)ary + sizeof(type) * n
n = (0x00400000 - (int)ary) / sizeof(int)
0x00400000 的内容就是 ary[(0x00400000 - (int)ary) / sizeof(int)]
#include #include int main(){ int ary[5] = {1, 2, 3, 4, 5}; printf("%08x\r\n", ary[(0x00400000 - (int)ary) / sizeof(int)]); system("pause"); return 0;}
按 F10 进行单步调试,在搜索框中搜索 0x00400000,可以看到里面的内容是 4d5a9000 ,按照小尾方式排列就是 00905a4d。
编译执行,打印的值就是 00905a4d
也就是说,当学会数组的下标运算法则以后,内存中任何一个点,都可以访问,这时如果对内存结构又很熟悉。例如打游戏时,如果知道哪个地方放血量,哪个地方放防御力,哪个地方放攻击力,可以对其进行读写,那在游戏中就是逆天的存在。
通过调试找到程序入口点地址
编写程序
#include #include int main(){ int n = 0; int ary[5] = {1, 2, 3, 4, 5}; system("pause"); return 0;}
按 F10 进入单步调试模式,双击栈窗口的 mainCRTStartup()
找到 void mainCRTStartup() 第一个左括号的位置
void mainCRTStartup(#endif /* WPRFLAG */#endif /* _WINMAIN_ */ void){
按 F9 下断点
按 alt + 8 进入反汇编模式,可以看到程序的入口点地址是 00401410
通过计算方法找到程序入口点地址
进入调试状态找到 0x00400000 的地址,在往后数 3c 个位置,并取出里面的值,也就是 0x000000d8。
将取出来的 0x000000d8 加上 0x00400000,得出 0x004000d8,可以看到 PE 两个字。
在 0x004000d8 之后,在往后数两行半,也就是再往后数 40(十六进制 28)个,0x004000d8 + 0x28 = 0x00400100 。里面的值是 0x00001410。
将 0x00001410 加上 0x00400000 ,得出的结果 0x00401410 就是程序的入口点地址。
通过程序找到程序入口点地址
将上一内容进行简化,用程序实现找到程序入口点的位置。
取出 0x0040003c 的值
#include #include int main(){ int n = 0; int ary[5] = {1, 2, 3, 4, 5}; n = ary[(0x0040003c - (int)ary) / sizeof(int)]; printf("%08x\r\n", n); system("pause"); return 0;}
将取出来的值加上 0x00400000 ,再加上 0x28。
#include #include int main(){ int n = 0; int ary[5] = {1, 2, 3, 4, 5}; n = ary[(0x0040003c - (int)ary) / sizeof(int)]; n = n + 0x00400000 + 0x28; printf("%08x\r\n", n); system("pause"); return 0;}
以上一步得出的结果为地址,取出里面的值
#include #include int main(){ int n = 0; int ary[5] = {1, 2, 3, 4, 5}; n = ary[(0x0040003c - (int)ary) / sizeof(int)]; n = n + 0x00400000 + 0x28; n = ary[(n - (int)ary) / sizeof(int)]; printf("%08x\r\n", n); system("pause"); return 0;}
将上一步取得的值,加上 0x00400000 ,就是程序的入口点位置。
#include #include int main(){ int n = 0; int ary[5] = {1, 2, 3, 4, 5}; n = ary[(0x0040003c - (int)ary) / sizeof(int)]; n = n + 0x00400000 + 0x28; n = ary[(n - (int)ary) / sizeof(int)]; printf("%08x\r\n", n + 0x00400000); system("pause"); return 0;}
END
扫码关注
更多精彩