[Asm] 纯文本查看 复制代码#include "iostream"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

class Utils

{

public:

static vector uint64ToByteList(uint64_t value)

{

vector byteList;

for (size_t i = 0; i < 8; i++)

{

int tempValue = value;

tempValue = value << (8 * (7 - i));

tempValue = tempValue >> 8 * 8;

byteList.push_back(tempValue);

}

return byteList;

}

static vector uint32ToByteList(uint32_t value, int number = 4)

{

vector byteList;

if (number <= 0 || number > 4)

{

return byteList;

}

for (size_t i = 0; i < number; i++)

{

int tempValue = value;

if (i == 0)

{

tempValue = value << 24;

}

if (i == 1)

{

tempValue = value << 16;

}

if (i == 2)

{

tempValue = value << 8;

}

tempValue = tempValue >> 24;

byteList.push_back(tempValue);

}

return byteList;

}

static vector uint16ToByteList(uint32_t value)

{

vector byteList;

int tempValue = 0;

tempValue = value << 8 >> 8;

byteList.push_back(tempValue);

tempValue = value >> 8;

byteList.push_back(tempValue);

return byteList;

}

void static print_byteList_hexArray(vector data)

{

for (const auto& item : data)

{

cout << std::hex << (int)item << " ";

}

cout << endl;

}

string static byteListToString(vector data)

{

std::string res;

res.insert(res.begin(), data.begin(), data.end());

return res;

}

void static print_regs(struct user_regs_struct* reg_addr)

{

printf("--------------------------\n");

printf("print regs\n");

printf("rax=0x%016" PRIx64 "\n", reg_addr->rax);

printf("rcx=0x%016" PRIx64 "\n", reg_addr->rcx);

printf("rdx=0x%016" PRIx64 "\n", reg_addr->rdx);

printf("rbx=0x%016" PRIx64 "\n", reg_addr->rbx);

printf("rsp=0x%016" PRIx64 "\n", reg_addr->rsp);

printf("rbp=0x%016" PRIx64 "\n", reg_addr->rbp);

printf("rsi=0x%016" PRIx64 "\n", reg_addr->rsi);

printf("rdi=0x%016" PRIx64 "\n", reg_addr->rdi);

printf("rip=0x%016" PRIx64 "\n", reg_addr->rip);

printf("--------------------------\n");

}

};

class KKptrace

{

private:

pid_t targetPid = 0;

const char localLibcPath[39] = "/usr/lib/x86_64-linux-gnu/libc-2.32.so";

void* getLibcBaseAddr(pid_t pid, const char* localLibcPath) {

char filepath[512];

void* moduleBaseAddr = NULL;

snprintf(filepath, 512, "/proc/%d/maps", pid);

FILE* f = fopen(filepath, "r");

char line[512];

while (!feof(f)) {

memset(line, 0, 512);

fgets(line, 512, f);

// printf(line);

string lineStr = line;

if (lineStr.find(localLibcPath) != -1)

{

int index = lineStr.find("-");

string addrStr = lineStr.substr(0, index);

stringstream ss;

//puts(lineStr.c_str());

ss << hex << addrStr.c_str();

ss >> moduleBaseAddr;

break;

}

}

if (moduleBaseAddr == NULL)

{

cout << "getLibcBaseAddr() error,moduleName=" << localLibcPath << endl;

}

fclose(f);

return moduleBaseAddr;

}

void* getRemoteFuncAddr(void* localFuncAddr, const char* libcName, pid_t remotePid = 0, void* remoteLibcBaseAddr = NULL) {

void* remoteFuncAddr;

if (remotePid == 0)

{

remotePid = targetPid;

}

if (remoteLibcBaseAddr == NULL)

{

remoteLibcBaseAddr = getLibcBaseAddr(remotePid, libcName);

}

void* localLibcBaseAddr = getLibcBaseAddr(getpid(), libcName);

if (localLibcBaseAddr==NULL || remoteLibcBaseAddr==NULL)

{

return NULL;

}

remoteFuncAddr = (void*)(uint64_t)localFuncAddr - (uint64_t)localLibcBaseAddr + (uint64_t)remoteLibcBaseAddr;

return remoteFuncAddr;

}

public:

// attachment is premise of all opeartions

bool isAttachSuccess = false;

struct user_regs_struct callBefore_regs;

bool attach(pid_t pid)

{

targetPid = pid;

isAttachSuccess = false;

int status = 0;

if (ptrace(PTRACE_ATTACH, targetPid, NULL, 0) < 0)

{

printf("KKptrace->attach():attach process error, pid:%d\n", targetPid);

return false;

}

printf("KKptrace->attach(): process success pid:%d\n", targetPid);

waitpid(targetPid, &status, WUNTRACED);

isAttachSuccess = true;

return true;

}

bool ptrace_continue()

{

if (ptrace(PTRACE_CONT, targetPid, NULL, NULL) < 0)

{

printf("KKptrace->attach():ptrace continue error, pid:%d", targetPid);

return false;

}

return true;

}

bool detach()

{

//kill(targetPid, SIGSTOP);

//waitpid(targetPid, NULL, 0);

if (ptrace(PTRACE_DETACH, targetPid, NULL, 0) < 0)

{

printf("KKptrace->attach():detach process error, pid:%d\n", targetPid);

return false;

}

return true;

}

uint32_t memoryRead_uint32(void* addr)

{

if (!isAttachSuccess)

{

return 0;

}

uint32_t re = ptrace(PTRACE_PEEKTEXT, targetPid, addr, 0);

return re;

}

vector memoryRead_bytes(void* addr, int number)

{

int i = 0;

uint32_t tempValue = 0;

vector reByteList;

vector tempByteList;

for (i = 0; i < number / 4; i++)

{

tempValue = memoryRead_uint32(addr + i * 4);

//cout << "readMemory_bytes.for->tempValue=" << std::hex << tempValue << endl;

tempByteList = Utils::uint32ToByteList(tempValue, 4);

reByteList.insert(reByteList.end(), tempByteList.begin(), tempByteList.end());

}

if (number % 4)

{

tempValue = memoryRead_uint32(addr + i * 4);

tempByteList = Utils::uint32ToByteList(tempValue, number % 4);

reByteList.insert(reByteList.end(), tempByteList.begin(), tempByteList.end());

}

return reByteList;

}

bool memoryWrite_string(void* addr, string data)

{

if (data.size() == 0)

{

return false;

}

vector byteList;

for (size_t i = 0; i < data.size(); i++)

{

byteList.push_back(data[i]);

}

byteList.push_back(0);

return memoryWrite_bytes(addr, byteList);

}

bool memoryWrite_chars(void* addr, const char* data)

{

vector byteList;

for (size_t i = 0; data[i] != 0; i++)

{

byteList.push_back(data[i]);

}

byteList.push_back(0);

return memoryWrite_bytes(addr, byteList);

}

bool memoryWrite_bytes(void* addr, vector data)

{

if (!isAttachSuccess)

{

return false;

}

uint64_t writeValue = 0;

void* writeAddr = addr;

size_t i;

for (i = 0; i < data.size() / 8; i++)

{

writeValue = 0;

for (size_t j = 0; j < 8; j++)

{

uint64_t tempValue = 0;

tempValue = data[i * 8 + j];

tempValue = tempValue << (8 * j);

writeValue = writeValue + tempValue;

}

writeAddr = addr + 8 * i;

if (ptrace(PTRACE_POKETEXT, targetPid, writeAddr, writeValue) < 0)

{

return false;

}

}

int yu = data.size() % 8;

if (yu)

{

writeValue = 0;

writeAddr = addr + 8 * i;

// 未对齐64bit的情况,需要先取值再覆盖。

vector readByteList = memoryRead_bytes(writeAddr, 8);

for (size_t j = yu; j < 8; j++)

{

uint64_t tempValue = readByteList[j];

tempValue = tempValue << 8 * j;

writeValue = writeValue + tempValue;

}

for (size_t j = 0; j < yu; j++)

{

uint64_t tempValue = 0;

tempValue = data[i * 8 + j];

tempValue = tempValue << (8 * j);

writeValue = writeValue + tempValue;

}

if (ptrace(PTRACE_POKETEXT, targetPid, writeAddr, writeValue) < 0)

{

return false;

}

}

return true;

}

bool memoryWrite_int64(void* addr, int64_t value)

{

return memoryWrite_bytes(addr, Utils::uint64ToByteList(value));

}

bool memoryWrite_uint64(void* addr, uint64_t value)

{

return memoryWrite_bytes(addr, Utils::uint64ToByteList(value));

}

bool memoryWrite_int32(void* addr, int32_t data)

{

return memoryWrite_bytes(addr, Utils::uint32ToByteList(data));

}

bool memoryWrite_uint32(void* addr, uint32_t data)

{

return memoryWrite_bytes(addr, Utils::uint32ToByteList(data));

}

bool memoryWrite_int16(void* addr, int16_t data)

{

return memoryWrite_bytes(addr, Utils::uint16ToByteList(data));

}

bool memoryWrite_uint16(void* addr, uint16_t data)

{

return memoryWrite_bytes(addr, Utils::uint16ToByteList(data));

}

bool memoryWrite_int8(void* addr, int8_t data)

{

vector byteList{ (uint8_t)data };

return memoryWrite_bytes(addr, byteList);

}

bool memoryWrite_uint8(void* addr, uint8_t data)

{

vector byteList{ data };

return memoryWrite_bytes(addr, byteList);

}

bool getRegs(struct user_regs_struct* regs_addr)

{

if (ptrace(PTRACE_GETREGS, targetPid, NULL, regs_addr) < 0)

{

printf("KKptrace->getRegs(): fail\n");

return false;

}

return true;

}

void regsPrint()

{

struct user_regs_struct regs;

getRegs(®s);

Utils::print_regs(®s);

}

bool setRegs(struct user_regs_struct* regs_addr, bool isPrintSetBeforeAndAfter = false)

{

struct user_regs_struct regs;

if (isPrintSetBeforeAndAfter)

{

puts("set before");

Utils::print_regs(regs_addr);

}

if (ptrace(PTRACE_SETREGS, targetPid, NULL, regs_addr) < 0)

{

printf("KKptrace->setRegs(): fail\n");

return false;

}

if (isPrintSetBeforeAndAfter)

{

puts("set before");

getRegs(®s);

Utils::print_regs(®s);

}

return true;

}

void call_begin()

{

// 1、获取并保留当前寄存器环境,以便函数执行完毕后恢复程序正常流程

getRegs(&callBefore_regs);

}

void call_end(bool isWaitToRun=false)

{

// 将寄存器恢复到call之前的状态

setRegs(&callBefore_regs);

int state = 0;

ptrace_continue();

if (isWaitToRun)

{

waitpid(targetPid, &state, WUNTRACED);

}

}

bool call(void* localFunc, vector paramList, int64_t* reValue=NULL,const char* libcName = NULL)

{

string libcNameStr = "libc-2.32.so";

if (libcName == NULL || string(libcName).size() == 0)

{

libcName = libcNameStr.c_str();

}

void* funcAddr = getRemoteFuncAddr((void*)localFunc, libcName);

if (funcAddr==NULL)

{

return false;

}

int64_t re = call_funcAddr(funcAddr, paramList);

if (reValue)

{

*reValue = re;

}

return true;

}

int64_t call_funcAddr(void* targetFuncAddr, vector paramList)

{

struct user_regs_struct regs_ori;

struct user_regs_struct regs;

getRegs(®s_ori);

memcpy(®s, ®s_ori, sizeof(regs_ori));

// 获取当前寄存器环境

// 多于6个参数通过栈传递

regs.rsp -= sizeof(void*);

size_t errRet = 0;

// 返回地址弄成0导致错误停止

memoryWrite_int64((void*)regs.rsp, 0);

// 前6个参数 通过寄存器传参

switch (paramList.size()) {

case 6:

regs.r9 = paramList[5];

case 5:

regs.r8 = paramList[4];

case 4:

regs.rcx = paramList[3];

case 3:

regs.rdx = paramList[2];

case 2:

regs.rsi = paramList[1];

case 1:

regs.rdi = paramList[0];

break;

}

// 参数>6个,后续参数需要压栈。

if (paramList.size() > 6) {

regs.rsp -= (paramList.size() - 6) * sizeof(long);

for (size_t i = 6; i < paramList.size(); i++)

{

memoryWrite_int64((void*)regs.rsp + i * 8, paramList[6 + i]);

}

}

// 通过修改RIP,修改CPU执行位置

regs.rax = 0;

regs.rip = (unsigned long long) targetFuncAddr;

setRegs(®s);

int state = 0;

ptrace_continue();

waitpid(targetPid, &state, WUNTRACED);

getRegs(®s);

uint64_t reValue = regs.rax;

return reValue;

}

/**

* [url=home.php?mod=space&uid=190858]@brief[/url] 将模块注入

* [url=home.php?mod=space&uid=952169]@Param[/url] modulePath 模块路径,例如./test.so

* @param funcName 函数名,默认为空,为空则只load so文件 不执行

* @param isRestore 注入后是否恢复程序正常运行,默认恢复;若设置不恢复,则需要手动调用call_end();

* @param isRestore 注入后是否恢复程序正常运行,默认恢复;若设置不恢复,则需要手动调用call_end();

*

* [url=home.php?mod=space&uid=155549]@Return[/url] 返回说明

* -false fail

* -true succeed

*/

bool inject(const char* modulePath, const char *funcName=NULL,bool isRestore = true,int64_t* reValue=NULL)

{

bool isCallSucess = false;

vector paramList;

call_begin();

// 分配内存地址

// mmap(0,0x100,可读可写可执行,…)

paramList.clear();

paramList.push_back(0);

paramList.push_back(0x100);

paramList.push_back(PROT_READ | PROT_WRITE | PROT_EXEC);

paramList.push_back(MAP_ANONYMOUS | MAP_PRIVATE);

paramList.push_back(0);

paramList.push_back(0);

int64_t remoteBuffer;

call((void*)mmap, paramList,&remoteBuffer);

if (remoteBuffer == -1)

{

printf("mmap() fail");

return false;

}

printf("mmap sucess addr=%p\n", remoteBuffer);

char realPath[500];

realpath(modulePath, realPath);

memoryWrite_chars((void*)remoteBuffer, realPath);

// 动态加载so文件

// libcAddr=dlopen(realPath,RTLD_NOW|RTLD_GLOBAL)

paramList.clear();

paramList.push_back(remoteBuffer);

paramList.push_back(RTLD_NOW | RTLD_GLOBAL);

int64_t moduleHandle;

isCallSucess = call((void*)dlopen, paramList, &moduleHandle, "libdl-2.32.so");

if (!isCallSucess)

{

return false;

}

printf("moduleHandle=%p\n", moduleHandle);

if (!moduleHandle)

{

paramList.clear();

int64_t dlerrorReAddr;

call((void*)dlerror, paramList, &dlerrorReAddr,"libdl-2.32.so");

printf("dlopen() error,text=");

paramList.push_back(dlerrorReAddr);

call((void*)puts, paramList);

return false;

}

// 如果函数名为空,则只load so 不执行函数;

if (funcName==NULL || string(funcName).size()==0)

{

return true;

}

memoryWrite_chars((void*)remoteBuffer, funcName);

// 获取函数地址

// libcAddr=dlsym(libcAddr,funcName)

paramList.clear();

paramList.push_back(moduleHandle);

paramList.push_back(remoteBuffer);

int64_t funcAddr;

isCallSucess = call((void*)dlsym, paramList,&funcAddr, "libdl-2.32.so");

if (!isCallSucess)

{

return false;

}

printf("func addr=%p\n", funcAddr);

if (!funcAddr)

{

printf("dlsym() error");

return false;

}

// 执行已经加载成功的模块中的函数

paramList.clear();

int64_t re = call_funcAddr((void*)funcAddr, paramList);

if (reValue)

{

*reValue = re;

}

if (isRestore)

{

call_end();

}

return true;

}

};

int main()

{

KKptrace* kkptrace = new KKptrace();

pid_t forkPid = fork();

if (forkPid == 0)

{

char* argv[] = {};

execv("/home/ubuntu/Desktop/android_learningRoad/ptrace_reject/plsInjectMe", NULL);

return 0;

}

sleep(1);

cout << "childPid=" << forkPid << endl;

//pid_t forkPid;

//cin >> forkPid;

if (!kkptrace->attach(forkPid))

{

return 0;

}

int64_t re;

kkptrace->inject("/home/ubuntu/Desktop/android_learningRoad/ptrace_reject/libtest.so", "testEntry", true, &re);

cout << "injectAfterCall_re=" << re << endl;

puts("pls input any key exit");

getchar();

return 0;

}

ptrace linux,【ptrace注入】linux下ptrace注入器的实现相关推荐

  1. linux命令注入,Linux kernel本地命令注入漏洞

    Linux kernel本地命令注入漏洞 2005-10-19 eNet&Ciweek Linux kernel 2.2.6 Linux kernel 2.2.5 Linux kernel 2 ...

  2. Linux ptrace 原理,从gdb原理学习ptrace调用

    Linux的ptrace系统调用,是Android二进制hook框架adbi的核心.因此学习adbi之前,先学习一下ptrace()函数. ptrace介绍 ptrace可以拆开来,看作Process ...

  3. Linux ptrace系统调用详解:利用 ptrace 设置硬件断点

    <GDB调试之ptrace实现原理> <C语言程序调用栈:backtrace+backtrace_symbols+backtrace_symbols_fd> <strac ...

  4. Linux中/proc目录下文件详解

    Linux中/proc目录下文件详解(一) 声明:可以自由转载本文,但请务必保留本文的完整性. 作者:张子坚 email:zhangzijian@163.com 说明:本文所涉及示例均在fedora ...

  5. transmission Linux(debian)下的BT下载客户端安装

    transmission Linux(debian)下的BT下载客户端安装 转载于:https://blog.51cto.com/2042617/1597540

  6. Linux(ubuntu)下安装anaconda(64位)并配置jupyter notebook远程访问

    Linux(ubuntu)下安装anaconda(64位)并配置jupyter notebook远程访问 Anaconda指的是一个开源的Python发行版本,其包含了conda.Python等180 ...

  7. 蜗蜗 Linux内核芬妮下,Linux内核的整体架构

    作者:蜗蜗 发布于:2014-2-21 13:23 分类:Linux内核分析 1. 前言 本文是"Linux内核分析"系列文章的第一篇,会以内核的核心功能为出发点,描述Linux内 ...

  8. linux es连接mysql_LINUX下使用elasticsearch-jdbc工具实现MySQL同步到ElasticSearch 以及linux 64位centos系统安装jdk1.8...

    第一步:环境匹配 1)elasticsearch 2.3.3 成功安装部署 2)mysql安装成功,增删改查无误~~. 3)要保证elasticsearch-jdbc的版本要与elasticsearc ...

  9. windows命令行下访问linux,Windows支持直接访问Linux子系统文件:你的下一台Linux何必是Linux...

    原标题:Windows支持直接访问Linux子系统文件:你的下一台Linux何必是Linux 晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI 微软,致力于做最好的Linux发行版. 今天, ...

  10. Linux快捷键-命令行下

    LINUX中命令行下是没有鼠标的,所以所有的操作只能通过键盘来实现.确实,鼠标对于电脑而言感觉还是很重要的,相对与Windows,Linux在易操作性上差的很多.所以,对于我们技术人员来讲,刚开始学习 ...

最新文章

  1. WebStorm配置SVN
  2. 你的电池再充几次电就报废?机器学习帮你预测电池寿命
  3. 抖音数据统计_“彭十六elf”单条视频获赞200W+,荣登抖音TOP20丨红人榜
  4. allegro差分信号走线_浅谈硬件设计中的一些思路和方法(5)—信号系统,又学到了...
  5. 大学加权平均分计算器_英国排名前20的大学GPA要求
  6. 2019牛客暑期多校训练营(第三场)J - LRU management (模拟+list+unorder_map)
  7. 解决devenv.exe应用程序错误,应用程序发生异常
  8. 基于水色图像的水质评价
  9. 年底无心工作?给个摸鱼好去处。中国超级英雄【一方净土】,进来看看嘛
  10. Quest2有线串联steamVR
  11. 在Pycharm中,全文搜索、替换,以及单独文件搜索、替换!
  12. Windows笔记本-U盘无法完成格式化
  13. 三秒让你学会公私网地址转换(NAT)
  14. css大图切割,利用CSS切割图片技术来动态显示图片
  15. 微信小程序——设置tabBar
  16. 浏览器2014官方下载
  17. win10 python3.8.10下ipython无响应处理
  18. 网站历史博物馆来过反爬
  19. 【Java】变量的分类(作用域,初始值,生命周期)
  20. 小白怎样学习数据分析?

热门文章

  1. musescore源码_业余歌剧歌手如何使用MuseScore
  2. 为什么Qt会有 QT_BEGIN_NAMESPACE宏
  3. NepCTF2022 WP
  4. 绑定内联样式 :style
  5. 【转载】System.Data.ParameterDirection 参数的说明
  6. “全国十佳新锐领军程序员”出炉,小i机器人朱频频等获评
  7. tcpdump抓包分段
  8. 2022无线蓝牙耳机排行榜,2022最值得入手的蓝牙耳机品牌
  9. python判断用户名是否合法_Python校验用户名是否合法示例
  10. 全球及中国再生水行业十四五利用前景与运营布局规划报告2022版