1. 程式人生 > >如何在linux下閱讀源碼以及提取寫簡單demo

如何在linux下閱讀源碼以及提取寫簡單demo

lse AD debian control %d aging sca view cmd

//如何在linux下閱讀源碼以及提取寫demo
這裏以 ps 為例
用到的工具有 clion
先查看 ps 路徑
which

root@ubuntu:~# which ps
/bin/ps
root@ubuntu:~# 

查看源碼包
dpkg

root@ubuntu:~# dpkg -S /bin/ps
procps: /bin/ps
root@ubuntu:~# 

使用 apt-get 下載(這裏可能會報xxxxxxxx cannot be authenticated. 更新下就好 sudo apt-key update sudo apt-get update)
(它會下載很多東西 只關心源碼文件就好這裏是procps-3.3.9)

root@ubuntu:~# dpkg -S /bin/ps
procps: /bin/ps
root@ubuntu:~# ls
ClionProjects  Documents  manpages-zh-1.5.1         Music     Public     Videos
Desktop        Downloads  manpages-zh-1.5.1.tar.gz  Pictures  Templates
root@ubuntu:~# cd Desktop/
root@ubuntu:~/Desktop# ls
root@ubuntu:~/Desktop# apt-get source procps
Reading package lists... Done
Building dependency tree       
Reading state information... Done
NOTICE: ‘procps‘ packaging is maintained in the ‘Git‘ version control system at:
git://git.debian.org/collab-maint/procps.git
Need to get 612 kB of source archives.
Get:1 http://us.archive.ubuntu.com/ubuntu/ trusty-updates/main procps 1:3.3.9-1ubuntu2.3 (dsc) [2,164 B]
Get:2 http://us.archive.ubuntu.com/ubuntu/ trusty-updates/main procps 1:3.3.9-1ubuntu2.3 (tar) [561 kB]
Get:3 http://us.archive.ubuntu.com/ubuntu/ trusty-updates/main procps 1:3.3.9-1ubuntu2.3 (diff) [49.1 kB]
Fetched 612 kB in 46s (13.3 kB/s)
gpgv: Signature made 2018年05月14日 星期一 05時38分54秒 PDT using RSA key ID A744BE93
gpgv: Can‘t check signature: public key not found
dpkg-source: warning: failed to verify signature on ./procps_3.3.9-1ubuntu2.3.dsc
dpkg-source: info: extracting procps in procps-3.3.9
dpkg-source: info: unpacking procps_3.3.9.orig.tar.xz
dpkg-source: info: unpacking procps_3.3.9-1ubuntu2.3.debian.tar.gz
dpkg-source: info: applying uptime_test
dpkg-source: info: applying ignore_eaccess.patch
dpkg-source: info: applying testsuite_unsupp
dpkg-source: info: applying pmap_test
dpkg-source: info: applying libtool-update.diff
dpkg-source: info: applying /p_pid-enum.diff
dpkg-source: info: applying ignore_erofs.patch
dpkg-source: info: applying CVE-2018-1122.patch
dpkg-source: info: applying CVE-2018-1123.patch
dpkg-source: info: applying CVE-2018-1124.patch
dpkg-source: info: applying CVE-2018-1125.patch
dpkg-source: info: applying CVE-2018-1126.patch
dpkg-source: info: applying pmap_new_kernel.patch
root@ubuntu:~/Desktop# 

技術分享圖片
打開 clion 導入項目(註冊可以用遠程服務器http://idea.imsxm.com)
在 clion 裏就可以搜索指定目錄下所有文件中的字符串了(跟代碼審計一樣)

技術分享圖片
可以全選也可以默認
技術分享圖片

點擊項目
技術分享圖片
可以直接 ok查看 或者看預覽(preview)
技術分享圖片
找到 ps 真正的 main 函數:
其它用法就是clion 的用法了
如:可以查看函數、變量被誰引用了等等
技術分享圖片
技術分享圖片
這裏就直接給出我隨便提取的 demo(功能有 遍歷進程 與特定進程的內存)

#include <iostream>
#include <cstring>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ptrace.h>
#include <wait.h>

void test1(){
    // alt + enter  排錯
    // ctrl + q     查看文檔
    FILE* fp = fopen("hello.txt", "a+");
    if(fp == NULL){
        std::cout << "open file error" << std::endl;
        return;
    }

    char szBuf[100] = {"hello world!"};
    fwrite(szBuf,strlen(szBuf),1,fp);

    fclose(fp);
}

void test2(){
    // alt + enter  排錯
    // ctrl + q     查看文檔
    FILE* fp = fopen("hello.txt", "r+");
    if(fp == NULL){
        std::cout << "open file error" << std::endl;
        return;
    }

    int nFileSize = 0;
    struct stat stcFileInfo = {0};
    stat("hello.txt", &stcFileInfo);
    nFileSize = stcFileInfo.st_size;

    char szBuf[100] = {};
    fread(szBuf,nFileSize,1,fp);

    fclose(fp);

    printf("read content : %s ",szBuf);

}

void test3(){
    // 1. open file
    int fd = open("hello1.txt",
                  O_WRONLY | O_CREAT,
                  S_IRWXU | S_IRWXG | S_IRWXO);
    if(fd == -1){
        perror("open error");
        return;
    }
    // 2. write file
    char szBuf[100] = {"hello world!"};
    int nRet = write(fd, szBuf, strlen(szBuf));
    if(nRet == -1){
        perror("write error");
        return;
    }

    // 3. close file
    close(fd);

}

void test4(){
    // 1. open file
    int fd = open("hello1.txt",
                  O_RDONLY);
    if(fd == -1){
        perror("open error");
        return;
    }
    // 2. write file
    int nFileSize = 0;
    struct stat stcFileInfo = {0};
    stat("hello.txt", &stcFileInfo);
    nFileSize = stcFileInfo.st_size;

    char szBuf[100] = {0};
    int nRet = read(fd, szBuf, nFileSize);
    if(nRet == -1){
        perror("read error");
        return;
    }

    // 3. close file
    close(fd);

    printf("read content 1 : %s ",szBuf);

}

void enumProcess(){
    struct dirent *ent;          /* dirent handle */
    DIR *dir;
    int ouruid;
    int found_a_proc;
    found_a_proc = 0;
    ouruid = getuid();
    dir = opendir("/proc");
    while(( ent = readdir(dir) )){
        if(*ent->d_name<‘0‘ || *ent->d_name>‘9‘) continue;
        int pid = atoi(ent->d_name);

        char p_cmd[16] = {0};
        char buf[800]; /* about 40 fields, 64-bit decimal is about 20 chars */
        int num;
        int fd;
        char* tmp;
        struct stat sb; /* stat() used to get EUID */
        snprintf(buf, 32, "/proc/%d/stat", pid);
        if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return;
        num = read(fd, buf, sizeof buf - 1);
        fstat(fd, &sb);
        close(fd);
        buf[num] = ‘\0‘;
        tmp = strrchr(buf, ‘)‘);      /* split into "PID (cmd" and "<rest>" */
        *tmp = ‘\0‘;                  /* replace trailing ‘)‘ with NUL */

        sscanf(buf, "%d (%15c", &pid, p_cmd);  /* comm[16] in kernel */

        printf("pid = %d name = %s \r\n", pid, p_cmd);
    }
    closedir(dir);
}

void show_info(const char* buf, int size) {
    int count = 0;
    while(count < size){
        char ch = buf[count++];
        char show[10] = {0};
        sprintf(show, "%02x ", (u_char)ch);
        printf("%s",show);
        if ((count % 16) == 0){
            printf("\r\n");
        }
    }
}

void readProcessMem(int pid){

    // 1. attach process
    long lRet = ptrace(PTRACE_ATTACH, pid,NULL,NULL);
    if(lRet == -1){
        perror("ptrace err");
        return;
    }

    // 2. wait pid
    int stat = 0;
    __pid_t pid1 = waitpid(pid, &stat, 0);
    if(pid1 == -1){
        perror("waitpid err");
        return;
    }

    // 3. open mem
    char szBuf[100]  ={0};
    sprintf(szBuf, "/proc/%d/mem", pid);
    int fd = open(szBuf,O_RDONLY);
    if(fd == -1){
        perror("open err");
        return;
    }

    // 4. lseek pos
    int nRet = lseek(fd, 0x55c266915000, SEEK_SET);
    if(nRet == -1){
        perror("lseek err");
        return;
    }

    // 5. read mem
    char buf[0x200] = {0};
    nRet = read(fd, buf, 200);
    if(nRet == -1){
        perror("read err");
        return;
    }

    // 6. close
    close(fd);
    ptrace(PTRACE_DETACH, pid, 0,0);

    // 7, show
    show_info(buf, 200);

}

int main() {

    enumProcess();

    int pid = 0;
    printf("please input pid :");
    scanf("%d", &pid);

    readProcessMem(pid);

    getchar();

    return 0;
}

如何在linux下閱讀源碼以及提取寫簡單demo