注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

熊猫正正的博客

熊猫正正的天空

 
 
 

日志

 
 

Linux下代码注入实例  

2014-11-26 19:11:25|  分类: web安全渗透 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
【转】Linux下代码注入实例
前言

想学习下安卓上的注入,先了解了下linux平台上的进程注入吧!发现金龟子萌妹纸已经有实例了,就直接借鉴来用了。

0×1

参考文章 http://blog.csdn.net/estate66/article/details/6061642 (PS:这文章的代码有点问题,思路没问题的)

ptrace参考手册 http://linux.die.net/man/2/ptrace

0×2

目的是要插入一段代码到linux下已经运行的程序中

在linux下,没有办法向在windows下那样用开启远程线程的方法来注入代码,那么linux下有一个很强大的“工具”就是ptrace,ptrace可以附加一个正在运行的进程,然后获取和更改此进程的寄存器信息,甚至可以更改进程在内存中的数据。简单来说,就是可以控制附加进程的运行。

这篇文字的思路就是使用ptrace来附加我们自己编写一个进程,然后插入一段显示”hello world“的代码。

0×3

大家都知道 eip寄存器是存放CPU即将要执行的指令的地址的,也就是下一条指令的地址。那么我们即将用到的方法就是附加进程之后,修改被附加进程的当前eip指向的地址中的指令,并且保存原本指令,等待我们的指令被执行完成后,再恢复原本的指令。

0×4

首先我们编写一个测试程序,也就是被附加的进程

C++
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
 
int main()
{
    int i;
    for(i = 0; i < 10; i++)
    {
        printf("my counter:%d\n",i);
        sleep(2);
    }
    return 0;
}
使用gcc编译

0×5

下面我们封装两个函数,一个是用来获得eip寄存器指向地址的代码,一个是用来向eip寄存器的地址中存放自己的代码
void getdata(pid_t child, long addr, char * str, int len)
{
 
        //这个函数用来获得addr指向地址的长度为len字节的代码(len为我们shellcode的长度);
        char * laddr;
        int i, j;
        union u
        {
                long val;
                char chars[long_size];
        }data;
        i = 0
 
        //求商,因为ptrace的PTRACE_PEEKDATA选项每次是读取这个地址中的4字节的代码,所以下面先读取4的整数倍。
        j = len/long_size;
        laddr=str;
        while(i<j)
        {
                data.val=ptrace(PTRACE_PEEKDATA,child,addr+i*4,NULL);
                memcpy(laddr,data.chars,long_size);
                ++i;
                laddr+=long_size;
        }
 
        //这里求余,继续读取代码
        j = len % long_size;
        if(j!=0)
        {
                data.val=ptrace(PTRACE_PEEKDATA, child, addr+i*4, NULL);
                memcpy(laddr,data.chars,j);
        }
        str[len] = '\0';
}
下面是一个写数据的函数,思路和上面那个getdata差不多
void putdata(pid_t child, long addr, char* str, int len)
{
        int i,j;
        char * laddr;
        union u
        {
                long val;
                char chars[long_size];
        }data;
        i = 0;
        j = len/long_size;
        laddr=str;
        while(i<j)
        {
                memcpy(data.chars,laddr,long_size);
                ptrace(PTRACE_POKEDATA,child,addr+i*4,data.val);
                ++i;
                laddr+=long_size;
        }
        j = len %long_size;
        if(j!=0)
        {
                memcpy(data.chars,laddr,j);
                ptrace(PTRACE_POKEDATA,child,addr+i*4, data.val);
        }
}

main函数
#include <sys/ptrace.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/user.h>
 
const int long_size = sizeof(long);
 
int main(int argc, char* argv[])
{
 
        //这里保存想要附加进程的ID
        pid_t traced_process;
 
        //为了保存寄存器的值
        struct user_regs_struct regs, newregs;
        long ins;
        int k,h;
        int len=41;
 
        //构造的输出hello world的shellcode,上面的len是shellcode的长度
        char shellcode[]="\xeb\x15\x5e\xb8\x04\x00\x00\x00"
     "\xbb\x02\x00\x00\x00\x89\xf1\xba"
     "\x0c\x00\x00\x00\xcd\x80\xcc\xe8"
     "\xe6\xff\xff\xff\x48\x65\x6c\x6c"
     "\x6f\x20\x57\x6f\x72\x6c\x64\x0a\x00";
 
        //backup保存原始的代码
        char backup[len];
        long addr;
        if(argc != 2)
        {
                printf("command input error:\n");
                exit(1);
        }
 
        //将输入的第二个参数转换成整型
        traced_process=atoi(argv[1]);
 
        //附加进程
        ptrace(PTRACE_ATTACH,traced_process,NULL,NULL);
        wait(NULL);
 
        //获得当前寄存器
        ptrace(PTRACE_GETREGS, traced_process, NULL,&regs);
        // 打印eip
        ins = ptrace(PTRACE_PEEKTEXT,traced_process,regs.eip,NULL);
        printf("EIP:%lx instruction executed : %lx\n",regs.eip,ins);
 
        getdata(traced_process,regs.eip,backup,len);
        //打印原始代码
        printf("backup is : \n");
        for(k = 0 ;k  < 41; k++)
        {
                printf("%x ",backup[k]);
        }
        printf("\n");
        putdata(traced_process,regs.eip,shellcode,len);
        printf("shellcode is :\n");
 
        for(h = 0; h < 41; h++)
        {
                printf("%x ", shellcode[h]);
        }
        printf("\n");
 
        //重新设置寄存器
        ptrace(PTRACE_SETREGS, traced_process,NULL,&regs);
 
        //恢复运行程序,也就是从刚刚设置的eip处开始运行
        ptrace(PTRACE_CONT,traced_process,NULL,NULL);
 
        //等待子进程状态发生改变,shellcode中,使用了int 3断点使进程状态改变
        wait(NULL);
        printf("press the enter key to continue\n");
        getchar();
 
        //将原始代码拷贝回去
        putdata(traced_process,regs.eip,backup,len);
        ptrace(PTRACE_SETREGS,traced_process,NULL,&regs);
        printf("excute origion code\n");
        ptrace(PTRACE_DETACH,traced_process,NULL,NULL);
        return 0;
}

测试,首先运行刚刚的counter程序

使用命令 ./counter &

然后启动codeinjection程序
Linux下代码注入实例 - 熊猫正正 - 熊猫正正的博客
 

转自:http://0nly3nd.sinaapp.com/?p=529
  评论这张
 
阅读(88)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017