【Android 逆向】代码调试器开发 ( ptrace 函数 | 向进程内存写出数据 )

简介: 【Android 逆向】代码调试器开发 ( ptrace 函数 | 向进程内存写出数据 )

文章目录

一、向进程内存写出数据

二、写出流程

三、完整代码





一、向进程内存写出数据


向内存写出数据 : 每次最多能写出 4 字节 ;


ptrace(PTRACE_POKETEXT, m_nPid, (void*)pDestAddr, d.val);


参数一 : 写出数据标志 PTRACE_POKETEXT ;

参数二 : 进程号 PID ;

参数三 : 写出去数据的地址 ;

参数四 : 写出的数据内容 , 4 字节 ;





二、写出流程


向进程内存写出数据时 , 每次最多只能写出 4 字节数据 , 先根据读取的大小 , 计算出读取次数 ,


// 每次读取 4 字节 , 读取次数为 nSize / 4
  j = nSize / 4;


然后再计算出最后不足 4 字节的部分 ,


// 读取最后不满 4 个字节的数据 
  remain = nSize % 4;


读取数据时 , 先循环 j 次 , 写出 j x 4 字节数据 ,


for (i = 0; i < j; i++) {
  // 准备写出数据 , 从 laddr 拷贝到 d.chars
  memcpy(d.chars, laddr, 4);
  // 32 位的设备上 , 最长只能读取 4 字节 
  ptrace(PTRACE_POKETEXT, m_nPid, (void*)pDestAddr, d.val);
  pDestAddr += 4;
  laddr += 4;
  }



最后再读取一次末尾不足 4 字节的数据 ;


读取的时候 , 如果不足 4 字节 , 我们可以将数据直接读取出来 , 不影响程序运行 ; 写出的时候 , 如果写出数据不足 4 字节 , 是 3 字节 , 那么必须保证最后一位写出时 , 不会出错 , 原来进程中 第 4 位是什么数据 , 写出去时也必须是同样的数据 , 否则进程运行出错 ;


先 读取 当前进程内存的数据 ,


// 一次性必须写入 4 字节 , 如果不足 4 字节 , 先把数据读取出来 , 即读取 4 字节出来 
  d.val = ptrace(PTRACE_PEEKTEXT, m_nPid, (void*)pDestAddr, 0);


然后 , 设置数据 ; 假如数据有 3 字节 , 那么就将上述读取的 4 字节的前 3 个字节设置成我们要修改的数据 , 这就保证了第 4 个字节不会出错 ;


// 假如数据有 3 字节 , 那么就将上述读取的 4 字节的前 3 个字节设置成我们要修改的数据 
  //  这就保证了第 4 个字节不会出错 
  for (i = 0; i < remain; i++) {
    d.chars[i] = *laddr++;
  }


最后 , 将最终的 4 字节数据写入进程内存 ;


// 最后将最终的 4 字节数据写入进程内存
  ptrace(PTRACE_POKETEXT, m_nPid, (void*)pDestAddr, d.val);//整体写入


部分代码示例 :


// 写出末尾不足 4 字节的数据部分 
  //  读取的时候 , 如果不足 4 字节 , 我们可以将数据直接读取出来 , 不影响程序运行 
  //  写出的时候 , 如果写出数据不足 4 字节 , 是 3 字节 , 那么必须保证最后一位写出时 , 不会出错 , 
  //  原来进程中 第 4 位是什么数据 , 写出去时也必须是同样的数据 , 否则进程运行出错 
  if (remain > 0) {
  // 一次性必须写入 4 字节 , 如果不足 4 字节 , 先把数据读取出来 , 即读取 4 字节出来 
  d.val = ptrace(PTRACE_PEEKTEXT, m_nPid, (void*)pDestAddr, 0);
  // 假如数据有 3 字节 , 那么就将上述读取的 4 字节的前 3 个字节设置成我们要修改的数据 
  //  这就保证了第 4 个字节不会出错 
  for (i = 0; i < remain; i++) {
    d.chars[i] = *laddr++;
  }
  // 最后将最终的 4 字节数据
  ptrace(PTRACE_POKETEXT, m_nPid, (void*)pDestAddr, d.val);//整体写入
  }





三、完整代码


向进程内存写出数据完整代码 :


// pDestAddr 写出地址 , const char* pData 写出的数据 , size_t nSize 写出数据大小 
int CPtrace::write(char* pDestAddr, const char* pData, size_t nSize)
{
  uint32_t i, j, remain;
  // 写出数据的地址 , 该地址需要不断累加计算 , 记录写出的数据地址 
  const char *laddr;
  // 联合体 , 在同一个内存地址上 , 既可以以 long 类型解析这块数据 , 也可以以 char 数组类型解析这块数据
  union u {
  long val;
  char chars[sizeof(long)];
  } d;
  // 每次读取 4 字节 , 读取次数为 nSize / 4
  j = nSize / 4;
  // 读取最后不满 4 个字节的数据 
  remain = nSize % 4;
  // 写出数据准备 
  laddr = pData;
  for (i = 0; i < j; i++) {
  // 准备写出数据 , 从 laddr 拷贝到 d.chars
  memcpy(d.chars, laddr, 4);
  // 32 位的设备上 , 最长只能读取 4 字节 
  ptrace(PTRACE_POKETEXT, m_nPid, (void*)pDestAddr, d.val);
  pDestAddr += 4;
  laddr += 4;
  }
  // 写出末尾不足 4 字节的数据部分 
  //  读取的时候 , 如果不足 4 字节 , 我们可以将数据直接读取出来 , 不影响程序运行 
  //  写出的时候 , 如果写出数据不足 4 字节 , 是 3 字节 , 那么必须保证最后一位写出时 , 不会出错 , 
  //  原来进程中 第 4 位是什么数据 , 写出去时也必须是同样的数据 , 否则进程运行出错 
  if (remain > 0) {
  // 一次性必须写入 4 字节 , 如果不足 4 字节 , 先把数据读取出来 , 即读取 4 字节出来 
  d.val = ptrace(PTRACE_PEEKTEXT, m_nPid, (void*)pDestAddr, 0);
  // 假如数据有 3 字节 , 那么就将上述读取的 4 字节的前 3 个字节设置成我们要修改的数据 
  //  这就保证了第 4 个字节不会出错 
  for (i = 0; i < remain; i++) {
    d.chars[i] = *laddr++;
  }
  // 最后将最终的 4 字节数据
  ptrace(PTRACE_POKETEXT, m_nPid, (void*)pDestAddr, d.val);//整体写入
  }
  return PTERR_SUCCESS;
}
目录
相关文章
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1649 4
|
10月前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
1119 3
|
10月前
|
存储 大数据 Unix
Python生成器 vs 迭代器:从内存到代码的深度解析
在Python中,处理大数据或无限序列时,迭代器与生成器可避免内存溢出。迭代器通过`__iter__`和`__next__`手动实现,控制灵活;生成器用`yield`自动实现,代码简洁、内存高效。生成器适合大文件读取、惰性计算等场景,是性能优化的关键工具。
461 2
|
12月前
|
安全 数据库 Android开发
在Android开发中实现两个Intent跳转及数据交换的方法
总结上述内容,在Android开发中,Intent不仅是活动跳转的桥梁,也是两个活动之间进行数据交换的媒介。运用Intent传递数据时需注意数据类型、传输大小限制以及安全性问题的处理,以确保应用的健壯性和安全性。
701 11
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
3017 2
|
缓存 编解码 Android开发
Android内存优化之图片优化
本文主要探讨Android开发中的图片优化问题,包括图片优化的重要性、OOM错误的成因及解决方法、Android支持的图片格式及其特点。同时介绍了图片储存优化的三种方式:尺寸优化、质量压缩和内存重用,并详细讲解了相关的实现方法与属性。此外,还分析了图片加载优化策略,如异步加载、缓存机制、懒加载等,并结合多级缓存流程提升性能。最后对比了几大主流图片加载框架(Universal ImageLoader、Picasso、Glide、Fresco)的特点与适用场景,重点推荐Fresco在处理大图、动图时的优异表现。这些内容为开发者提供了全面的图片优化解决方案。
516 1
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1030 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
监控 Java Android开发
深入探索Android系统的内存管理机制
本文旨在全面解析Android系统的内存管理机制,包括其工作原理、常见问题及其解决方案。通过对Android内存模型的深入分析,本文将帮助开发者更好地理解内存分配、回收以及优化策略,从而提高应用性能和用户体验。
1233 38
|
监控 Java Android开发
深入探讨Android系统的内存管理机制
本文将深入分析Android系统的内存管理机制,包括其内存分配、回收策略以及常见的内存泄漏问题。通过对这些方面的详细讨论,读者可以更好地理解Android系统如何高效地管理内存资源,从而提高应用程序的性能和稳定性。
747 16
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
470 5