x86_64汇编调试程序初步
寄存器说明:
rdi 存第1个参数(值或地址) rsi 存第2个参数 rdx 存第3个参数 rcx 存第4个参数 r8 存第5个参数 r9 存第6个参数 rax 第1个返回值 rdx 第2个返回值 rbx、rbp、r12、r13、r14、r15 用作数据存储,遵循被调用者使用规则,调用子函数之前需要先保存 r10、r11 用作数据存储,遵循调用者使用规则,使用之前需要先保存 rsp 指向栈顶 |
观察参数传递,被调试的源代码如下:
/* 01 */ #include <string.h> /* 02 */ #include <unistd.h> /* 03 */ void f(int a, const char* b) { /* 04 */ write(1234, b, strlen(b)); /* 05 */ } /* 06 */ int main() { /* 07 */ f(2018, "hello\n"); /* 08 */ return 0; /* 09 */ } |
优化方式编译程序:
g++ -g -O2 -o x x.cpp |
实践目标:
在gdb中让write改写到标准输出。
设置两个观察点,一是main函数,二是write函数:
(gdb) b main (gdb) b write |
运行程序:
reakpoint 1, main () at x.cpp:6 6 /* 06 */ int main() { Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.tl2.3.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64 (gdb) n 7 /* 07 */ f(2018, "hello\n"); (gdb) disassemble Dump of assembler code for function main(): 0x0000000000400550 <+0>: sub $0x8,%rsp => 0x0000000000400554 <+4>: mov $0x400710,%esi // 0x400710为第二个参数的地址 0x0000000000400559 <+9>: mov $0x7e2,%edi // 0x7e2为第一个参数的值 0x000000000040055e <+14>: callq 0x400660 <f(int, char const*)> 0x0000000000400563 <+19>: xor %eax,%eax 0x0000000000400565 <+21>: add $0x8,%rsp 0x0000000000400569 <+25>: retq End of assembler dump. (gdb) p (char*)0x400710 $1 = 0x400710 "hello" (gdb) p 0x7e2 $2 = 2018 (gdb) s f (a=2018, b=0x400710 "hello") at x.cpp:3 3 /* 03 */ void f(int a, const char* b) { (gdb) info reg rax 0x400550 4195664 rbx 0x0 0 rcx 0x40 64 rdx 0x7fffffffe1a8 140737488347560 rsi 0x400710 4196112 // 第二个参数地址(4196112的十六进制为0x400710) rdi 0x7e2 2018 // 第一个参数的值2018(2018的十六进制为0x7e2) rbp 0x0 0x0 rsp 0x7fffffffe0a8 0x7fffffffe0a8 r8 0x7ffff75b5e80 140737343348352 r9 0x0 0 r10 0x7fffffffdd40 140737488346432 r11 0x7ffff7218b10 140737339558672 r12 0x40056c 4195692 r13 0x7fffffffe190 140737488347536 r14 0x0 0 r15 0x0 0 rip 0x400660 0x400660 <f(int, char const*)> eflags 0x202 [ IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) c Continuing. Breakpoint 2, 0x00007ffff72e0840 in write () from /lib64/libc.so.6 (gdb) info reg rax 0x5 5 rbx 0x0 0 rcx 0x10 16 rdx 0x5 5 // write的第三个参数值 rsi 0x400710 4196112 // write的第二个参数值 rdi 0x1234 4660 // write的第一个参数值 rbp 0x0 0x0 rsp 0x7fffffffe0a8 0x7fffffffe0a8 r8 0x7ffff75b5e80 140737343348352 r9 0x0 0 r10 0x7fffffffdc70 140737488346224 r11 0x7ffff72e0840 140737340377152 r12 0x40056c 4195692 r13 0x7fffffffe190 140737488347536 r14 0x0 0 r15 0x0 0 rip 0x7ffff72e0840 0x7ffff72e0840 <write> eflags 0x202 [ IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) p $rdi $4 = 4660 (gdb) set $rdi=7777 // 修改寄存器rdi的值 (gdb) p $rdi $6 = 7777 (gdb) set $rdi=1 (gdb) c Continuing. hello // 正常输出到了标准输出,如果不修改rdi的值,将看不到输出“hello” [Inferior 1 (process 6722) exited normally] |
掌握此基础,就可以用来修改无源代码的程序等,比如希望jstatd在指定的端口上监听,而不是一个值为0的随机端口号,请参见《防火墙内JVisualVM连接jstatd解决方案》。
x86_64汇编调试程序初步的更多相关文章
- 【原创】X86_64汇编、寄存器、内嵌汇编
整理的X86_64/X86汇编.寄存器.C内嵌汇编笔记,主要用于查阅使用. 目录 一.汇编语言 二.指令 数据传输指令 栈操作指令 push pop 运算指令 位操作 比较操作指令 标志寄存器 流控制 ...
- 【转载】汇编调试程序Debug使用
https://blog.csdn.net/Notzuonotdied/article/details/70888205
- 【转】怎样创建一个Xcode插件(Part 1)
原文:How To Create an Xcode Plugin: Part 1/3 原作者:Derek Selander 译者:@yohunl 译者注:原文使用的是xcode6.3.2,我翻译的 ...
- ObjC如何通过runtime修改Ivar的内存管理方式
ObjC如何通过runtime修改Ivar的内存管理方式 为什么要这么做? 在iOS 9之前,UITableView(或者更确切的说是 UIScrollView)有一个众所周知的问题: propert ...
- centos7 docker 安装 mysql5.7.24 导入12G的sql
先在CentOS7里面安装docker Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker .通过 uname - ...
- x64架构下Linux系统函数调用
原文链接:https://blog.fanscore.cn/p/27/ 一. 函数调用相关指令 关于栈可以看下我之前的这篇文章x86 CPU与IA-32架构 在开始函数调用约定之前我们需要先了解一下几 ...
- 《30天自制操作系统》笔记2 --- 初步了解汇编产生的二进制(Day1)
nask.exe应该就是nas kit(nas开发工具的意思),由于这个编译器是作者自己写的,所以这种汇编语言应该是作者改造出来的,所以我叫它nas汇编语言. 作者说nask是模仿nasm语法的,关于 ...
- ICS2019汇编实验在Linux下使用GDB调试程序
- iOS程序破解——ARM汇编基础
原文在此:http://www.cnblogs.com/mddblog/p/4951650.html 一.Thumb指令与ARM指令 Thumb指令为16位,因此存储代码的密度高,节省存储空间.但是功 ...
随机推荐
- 当前的开源SLAM方案
开源方案 传感器形式 地址链接 MonoSLAM 单目 https://github.com/hanmekim/SceneLib2 PTAM 单目 http://www.robots.ox.ac. ...
- 在Struts2框架中使用Servlet的API
1. 在Action类中也可以获取到Servlet一些常用的API * 需求:提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的 ...
- PAT 1066 图像过滤(15)(代码)
1066 图像过滤(15 分) 图像过滤是把图像中不重要的像素都染成背景色,使得重要部分被凸显出来.现给定一幅黑白图像,要求你将灰度值位于某指定区间内的所有像素颜色都用一种指定的颜色替换. 输入格式: ...
- Kali Linux 网络扫描秘籍
第三章 端口扫描(二) 作者:Justin Hutchens 译者:飞龙 协议:CC BY-NC-SA 4.0 3.6 Scapy 隐秘扫描 执行 TCP 端口扫描的一种方式就是执行一部分.目标端口上 ...
- N! (数组)
#include <iostream> using namespace std; ; int f[MAXN]; int main(){ int n; cin >> n; f[] ...
- (O)js核心:作用域链
作用域 在一个函数被调用的时候,函数的作用域才会存在.此时,在函数还没有开始执行的时候,开始创建函数的作用域: 函数作用域的创建步骤: 1.函数形参的声明. 2.函数变量的声明. 3.普通变量的声 ...
- [Centos] ERROR: Could not find useradd in chroot, maybe the install failed?
[mockbuild at localhost ~]$ mock -r centos-5-x86_64-testdev.cfg initinitcleanprepThis may take a whi ...
- 【解决办法--实测可行】Partition 1 does not start on physical sector boundary.
新的硬盘使用fdisk进行划分的时候有提示Partition 1 does not start on physical sector boundary.后面按网上找的办法,在fdisk进行分区的时候, ...
- Nginx 如何设置反向代理
网络结构如上图.可能你只有一个公网的Ip地址. 但是您的内网有个网站需要映射至外网.而又不想添加其它的非80端口.则你可以直接使用nginx来做反向代理即可.首先,配置nginx.conf文件. ht ...
- Java SE EE ME用处
Java SE: 又称J2SE,开发部署桌面应用程序: Java EE:又称J2EE,开发网站 Java ME:是做手机APP开发 EE在SE基础上构建,提供web服务.组件模型.管理和通信API