gdbgdb 修改内存进程内存怎样实现

格式: x /nfu &addr&说明x 是 examine 的缩写n表示要显示的内存单元的个数f表示显示方式, 可取如下值x 按十六进制格式显示变量。d 按十进制格式显示变量。u 按十进制格式显示无符号整型。o 按八进制格式显示变量。t 按二进制格式显示变量。a 按十六进制格式显示变量。i 指令地址格式c 按字符格式显示变量。f 按浮点数格式显示变量。u表示一个地址单元的长度b表示单字节,h表示双字节,w表示四字节,g表示八字节Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),t(binary), f(float), a(address), i(instruction), c(char) and s(string).Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes)举例x/3uh buf表示从内存地址buf读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十进制显示
阅读(...) 评论()新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 13, 距离下一级还需 187 积分
论坛徽章:0
/*test.c*/
#include &stdio.h&
int main()
& & printf(&第一步!^_^!&);
& & getchar();
& & printf(&第二步!^_^!&);
& & getchar();
& & return 0;
编译成test程序。
1、用IDA查看到,第二个文本&第二步!^_^!&的固定地址是:0x。
2、我把自己写的so库,注入到test进程中,用“memcpy”可以读取出地址:0x的文本为:&第二步!^_^!&。
3、但是同样用“memcpy”修改地址:0x的内容,一修改,程序就立刻崩溃。
4、以为是“memcpy”问题,就自己用内联汇编,写了代码,同样一修改,程序就崩溃。
5、以为是系统用户权限问题,换了root账号,也一样情况。
6、用gdb修改地址:0x的内容,修改成功,程序也没有崩溃。
本人是这星期,刚加入linux编程队伍,百度,google了2天多,也没有找出解决方法。在论坛搜捕了80多页的帖子,也没有找出解决方法。
请问各位大大,gdb修改进程内存的地址,是怎样实现的?
白手起家, 积分 118, 距离下一级还需 82 积分
论坛徽章:0
不了解,只能说说自己知道的,不见得正确。希望对你有帮助!
这两个字符串在内存区是常量区,应该是只读属性的!
GDB调试:可以认为自己开了一个池子,将需调试程序加到这个池子里,它就可以操作池子里面的所有东西,只要知道对应地址。
家境小康, 积分 1973, 距离下一级还需 27 积分
论坛徽章:9
本帖最后由 w_anthony 于
09:26 编辑
这个不是所在页没有可写权限么?win上要用VirtualProtect改所在页的读写权限,linux上可能是mmap之类的(我不太确定,linux上没干过这事),LZ可以试试
-----------------
找到了linux上应该是mprotect了:
& && & mprotect - control allowable accesses to a region of memory
& && & #include &sys/mman.h&
& && & int mprotect(const void *addr, size_t len, int prot);
DESCRIPTION
& && & The&&function&&mprotect() specifies the desired protection for the memory page(s) containing part or all of the
& && & interval [addr,addr+len-1].&&If an access is disallowed by the protection given&&it,&&the&&program&&receives&&a
& && & SIGSEGV.
白手起家, 积分 13, 距离下一级还需 187 积分
论坛徽章:0
& & mprotect这函数,在看雪查资料时,有位大侠说过,我也用上了,也是直接程序崩溃,提示信息“段错误”。
白手起家, 积分 13, 距离下一级还需 187 积分
论坛徽章:0
skychgg 发表于
不了解,只能说说自己知道的,不见得正确。希望对你有帮助!
这两个字符串在内存区是常量区,应该是只读属 ...
我也考虑过,只读这问题,也用过mprotect这函数, mprotect (memory, alloc_size, PROT_READ | PROT_WRITE);
设置了读和写,但还是不行,程序直接崩溃
白手起家, 积分 18, 距离下一级还需 182 积分
论坛徽章:0
本帖最后由 jwlsyxff 于
20:36 编辑
应该是内核交给用户的, 即便你是root也改不了内核的权限的东西.
家境小康, 积分 1769, 距离下一级还需 231 积分
论坛徽章:1
google gdb /strace 实现 或者 读代码。。。
以前有了解了一下,好像调用不少系统接口实现的
论坛徽章:0
& & ptrace
白手起家, 积分 13, 距离下一级还需 187 积分
论坛徽章:0
本帖最后由 ziyoyo147 于
00:24 编辑
很开心,这里的人这么热情。我来小结一下吧。
这两天,经过百度,google,和自己写代码,找了原因。
1、linux进程,分为5个段,文本段(代码段),数据段,BBS,堆,栈,文本段和数据段,都是被linux保护的,只能读取,不能写入,如果写入的话,就会提示“段错误”,进程退出。不过本人今天买的书到了,书中有一节内容是讲拦截这个“段错误”的,让程序不退出。就如win的异常处理。
2、gdb是应该是使用ptrace函数完成内存修改,具体做法,先用ptrace附加进程,再ptrace修改进程数据。这个过程我自己写代码实现了,可以用B进程修改A进程的数据。
不过这里又来问题了。
新问题:要修改自己进程的代码,就要用别的进程来修改,因为用ptrace,是无法附加自己。如我要修改A进程的代码,就要让B进程来操作。所以,写了个so库,注入到A进程,so库是无法修改A进程的代码。
百度了一下,有个高人解决了这问题,是自己写了驱动,去除了进程代码段和数据段的保护,但由于本人是新手,那个驱动,我就看不明了,也不清楚具体怎样操作。
请问各位大大,除了ptrace外,有没有其它方法实现修改进程代码段或数据段的数据?
感谢楼上各位热心解答,总算找到个好论坛。
稍有积蓄, 积分 280, 距离下一级还需 220 积分
论坛徽章:1
你的injected的code有问题,可能是mprotect用错了,有检查过mprotect的返回值吗?
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处新人专享好礼凡未购买过小册的用户,均可领取三张 5 折新人专享券,购买小册时自动使用专享券,最高可节省 45 元。小册新人 5 折券最高可省 15 元小册新人 5 折券最高可省 15 元小册新人 5 折券最高可省 15 元注:专享券的使用期限在领券的七天内。一键领取购买小册时自动使用专享券前往小册首页本活动仅适用于小册新用户知道了GDB 实现原理介绍 | 始于珞尘原文链接:
GDB 是调试程序的利器, 它可以在代码中设置断点, 在程序运行过程中修改变量值等. 你是不是也很好奇 GDB 是如何实现这些功能的? 本文会解答你的疑问, 并通过一些简单的代码来模拟其中的实现细节.
GDB 中的魔法般的操作底层都是通过 ptrace 调用来实现的, 在介绍 GDB 的具体实现细节前, 我们先来好好了解下 ptrace 调用.
从名字就可以看出 ptrace 系统调用是用于进程跟踪的, 当进程调用了 ptrace 跟踪某个进程之后:
调用 ptrace 的进程会变成被跟踪进程的父进程;
被跟踪进程的进程状态被标记为 TASK_TRACED;
发送给被跟踪子进程的信号 (SIGKILL 除外) 会被转发给父进程, 而子进程会被阻塞;
父进程收到信号后, 可以对子进程进行检查和修改, 然后让子进程继续执行;
在 man ptrace 中可以找到 ptrace 的定义原型:
#include &sys/ptrace.h&
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
其中 request 参数指定了我们要使用 ptrace 的什么功能, 大致可以分为以下几类:
PTRACE_ATTACH 或 PTRACE_TRACEME 建立进程间的跟踪关系;
PTRACE_TRACEME 是被跟踪子进程调用的, 表示让父进程来跟踪自己, 通常是通过 GDB 启动新进程的时候使用;
PTRACE_ATTACH 是父进程调用 attach 到已经运行的子进程中; 这个命令会有权限的检查, non-root 的进程不能 attach 到 root 进程中;
PTRACE_PEEKTEXT, PTRACE_PEEKDATA, PTRACE_PEEKUSR 等读取子进程内存/寄存器中保留的值;
PTRACE_POKETEXT, PTRACE_POKEDATA, PTRACE_POKEUSR 等修改被跟踪进程的内存/寄存器;
PTRACE_CONT,PTRACE_SYSCALL, PTRACE_SINGLESTEP 控制被跟踪进程以何种方式继续运行;
PTRACE_SYSCALL 会让被调用进程在每次 进入/退出 系统调用时都触发一次 SIGTRAP; strace 就是通过调用它来实现的, 在每次进入系统调用的时候读取出系统调用参数, 在退出系统调用的时候读取出返回值;
PTRACE_SINGLESTEP 会在每执行完一条指令后都触发一次 SIGTRAP; GDB 的 nexti, next 命令都是通过它来实现的;
PTRACE_DETACH, PTRACE_KILL 脱离进程间的跟踪关系;
当父进程在子进程之前结束时, trace 关系会被自动解除;
参数 pid 表示的是要跟踪进程的 pid, addr 表示要监控的被跟踪子进程的地址.
当我们用 GDB 设置断点时, GDB 会把断点处的指令修改成 int 3, 同时把断点信息及修改前的指令保存起来. 当被调试子进程运行到断点处时, 便会执行 int 3命令, 从而产生 SIGTRAP 信号. 由于 GDB 已经用 ptrace 和调试进程建立了跟踪关系, 此时的 SIGTRAP 信号会被发送给 GDB, GDB 通过和已有的断点信息做对比 (通过指令位置) 来判断这次 SIGTRAP 是不是一个断点.
如果是断点的话, 就回等待用户的输入以做进一步的处理. 如果用户的命令是继续执行的话, GDB 就会先恢复断点处的指令, 然后执行对应的代码.
可以看到断点的实现中需要 GDB 去修改被跟踪子进程的内存 (代码也是保存在内存中的), 下面就先介绍下如何通过 ptrace 去修改子进程的内存.
我们通过下面的例子来演示父进程如何修改子进程的内存:
父进程创建子进程, 并先让子进程 sleep 一段时间以保证父进程能更早运行;
父进程通过 PTRACE_ATTACH 来和子进程建立跟踪关系;
父进程修改子进程的内存数据;
父进程通过调用 PTRACE_CONT 让子进程恢复执行;
完整的代码如下所示:
#include &sys/ptrace.h&
#include &unistd.h&
#include &stdio.h&
#include &stdlib.h&
#include &stdint.h&
#define SHOW(call) ({ int _ret = (int)(call); printf("%s -& %d\n", #call, _ret); if (_ret & 0) { perror(NULL); }})
char changeme[] = "This is
int main (void) {
pid_t pid = fork();
char cdata[8];
} u = { "Hijacked" };
switch (pid) {
case 0: /* child */
printf("Children Message: %s\n", changeme);
perror("fork");
default: /* parent */
SHOW(ptrace(PTRACE_ATTACH, pid, 0, 0));
SHOW(ptrace(PTRACE_POKEDATA, pid, changeme, u.data));
SHOW(ptrace(PTRACE_CONT, pid, 0, 0));
printf("Parent Message: %s\n", changeme);
wait(NULL);
上面代码的输出是:
Children Message: Hijacked a test
ptrace(PTRACE_ATTACH, pid, 0, 0) -& 0
ptrace(PTRACE_POKEDATA, pid, changeme, u.data) -& 0
ptrace(PTRACE_CONT, pid, 0, 0) -& 0
Parent Message: This is
可以看出子进程中的字符串已经被修改了, 而父进程中的字符串依旧保持不变.
在调用 ptrace(PTRACE_POKEDATA, pid, changeme, u.data) 时, 最后一个参数实际上是按照 int64_t 来处理的.
这部分原理其实很简单, 但代码实现会稍微有些复杂. 等有人有需求时再写吧… To Be Done… :)
相关热门文章分享gdb调试程序之监控内存【七】
我的图书馆
gdb调试程序之监控内存【七】
gdb提供awtach rwatch watch来监控调试中变量或者内存的变化
awatch 命令
awtach [expr]
当debugger read或者write该expr时,debugger 停止
rwatch 命令
rwatch [expr]
当debugger read该expr时,debugger停止
watch [expr]
当debugger write该expr时,debugger停止
说明:expr可以是变量或者是内存地址
TA的最新馆藏[转]&[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢Linux下调试编写并调试C语言程序,怎么查看它的内存和CPU信息?GDB中可以实现吗?_百度知道
Linux下调试编写并调试C语言程序,怎么查看它的内存和CPU信息?GDB中可以实现吗?
我有更好的答案
内存和cpu是硬件的概念,在程序中只有被映射后的内存和线程/进程的概念,具体如何调度程序的内存地址和线程/进程的挂起和运行都是操作系统来做的。使用gdb能够查看当前程序各个变量的内存数据内容此时的内存地址对程序员来说是没什么用的(除非是做硬件开发,可能会需要),gdb还能够查看当前程序中那些线程被挂起或正在运行,但查询不到当前线程在哪个cpu上运行。
对啊对啊,就是想看操作系统怎么弄的,比如fork()以后怎么看它占用的内存信息,和CPU是怎么处理的,什么时候挂起什么时候继续执行,还有它占用的内存起始地址多少占了多少,要怎么看呀,Linux就一脸懵逼
回答被采纳,没法直接回复你的追问了,在这里说吧!无论在linux还是windows,你说的要求都是以看不了的。首先内存在操作系统层面有一个物理地址到逻辑地址的映射,各类硬件设备、虚拟内存都会占用一部分内存地址空间,操作系统会将这些内存地址空间和实际的物理内存一起进行内存管理。所以你看到的内存地址,不一定是真实的物理内存地址看到只是逻辑地址。在一个,cpu的调度。cpu的调度策略是取决于操作系统核心的,同样的linux,不同的核心版本可能调度cpu的方式都不一样。常用的程序语句sleep()或者互斥锁等等操作都会导致线程挂起,但当你的程序数量多于操作系统cpu数量时,cpu如何调度这些进程或者线程那就没法看到了。上述两个问题都可以在操作系统原理相关的书籍中找到。建议你去看一下操作系统相关的数据来了解操作系统对内存与cpu的管理策略。当然,书里面的都是比较旧或者比较基础的原理。真正的常用操作系统可能有着自己独特的优化方式。
采纳率:54%
可以用linux版的QT,很方便的。
是嘛,过几天我安装好了再请教
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 gdb 修改内存值 的文章

 

随机推荐