lvxuzhou


私信TA

用户名:lvxuzhou

访问量:106753

签 名:

lvxuzhou

等  级
排  名 47
经  验 12168
参赛次数 0
文章发表 56
年  龄 0
在职情况 学生
学  校 西安
专  业

  自我简介:

前言:

   本篇是上篇 黑客入门系列二 内存泄漏检测工具的完结篇,主要使用python和shell脚本做了二次封装

第一步 测试代码:

#include <stdio.h>
#include <stdlib.h>
static void fun(void)
{
  int *p1 = malloc(10);
  *p1 = 1;
  int *p2 = malloc(20); //内存泄漏
  *p2 = 2;
  free(p1);
}
static void fun1(void)
{
  int *p1 = malloc(100);
  *p1 = 1;
  int *p2 = malloc(200); //内存泄漏
  *p2 = 2;
  free(p1);
}
static void fun2(void)
{
  for (size_t i = 0; i < 10; i++)
  {
    int *p1 = malloc(300); //内存泄漏10次
    *p1 = 1;
  }
  int *p2 = malloc(400);
  *p2 = 2;
  free(p2);
}

int main(void)
{
  fun();
  fun1();
  fun2();
  return 0;
}

第二步 劫持代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/mman.h>
#include <syscall.h>
#include <execinfo.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <execinfo.h>
static void *(*mymalloc)(size_t) = NULL;
static void (*myfree)(void *) = NULL;
static int fd = 0;

void __attribute__((constructor)) init(void)
{
    mymalloc = dlsym(RTLD_NEXT, "malloc");
    myfree = dlsym(RTLD_NEXT, "free");
    if (!mymalloc)
    {
        fprintf(stderr, "unable to get malloc symbol!\n");
        exit(1);
    }
    if (!myfree)
    {
        fprintf(stderr, "unable to get free symbol!\n");
        exit(1);
    }

    fd = open("mem.log", O_CREAT | O_TRUNC | O_WRONLY, 0644);
    if (!fd)
    {
        fprintf(stderr, "unable to fopen!\n");
        exit(1);
    }
    fprintf(stderr, "init successfully wrapped!\n");
}
void *malloc(size_t size)
{
    void *p = mymalloc(size);
    const void *caller_addr = __builtin_return_address(0);
    char buf[100] = {0};
    sprintf(buf, "+ %p caller_addr %p size=%lu\n", p, caller_addr - 1, size);
    write(fd, buf, strlen(buf));
    return p;
}
void free(void *ptr)
{
    const void *caller_addr = __builtin_return_address(0);
    char buf[100] = {0};

    sprintf(buf, "- %p caller_addr %p free\n", ptr, caller_addr);
    write(fd, buf, strlen(buf));
    myfree(ptr);
}
void __attribute__((destructor)) end(void)
{
    close(fd);
    fprintf(stderr, "end successfully wrapped!\n");
}

第三步 python脚本:

import os
import subprocess


def Parsing(filename):
    men_lines_list = list()
    res={}
    with open(filename, "r") as fd:
        men_lines_list = fd.read().splitlines()
    
    for leak_item in men_lines_list:
        if leak_item.split()[1] not in res.keys():
            res[leak_item.split()[1]]=leak_item
        else:
            res.pop(leak_item.split()[1])
    cmd = 'addr2line -f -e helloworld -p -a '
    men_lines_list=res.values()
    for leak_item in men_lines_list:
        addr = leak_item.split()[-2]
        p = subprocess.Popen(cmd + addr, shell=True, stdout=subprocess.PIPE)
        res = p.stdout.read().split()
        resstring = leak_item.split()[0] + ' ' + leak_item.split()[1] + ' ' + ' 文件: ' + bytes.decode(
            res[3]) + ' 函数: ' + bytes.decode(res[1]) + ' 大小 : ' + leak_item.split()[-1]
        print(resstring)

if __name__ == '__main__':
    Parsing("mem.log")

第四步 shell脚本:

gcc example.c -o libexample.so -fPIC -shared -ldl  -g3   -lcstl
gcc  -g3  -no-pie helloworld.c   -o helloworld  
export LD_PRELOAD=./libexample.so
./helloworld
export LD_PRELOAD=
python3 addr2line.py

第五步 测试结果:

QQ图片20211014001746.png

 

0.0分

0 人评分

新上线《蓝桥杯辅导》课程,近五年的蓝桥杯省赛与国赛真题都有,从读题开始理解题意、梳理思路、实现代码再提交评测全过程,可有效提升获奖比例甚至进国赛!课程介绍、试听请猛击这里

  评论区

  • «
  • »