使用签名恢复二进制文件符号表

为了识别静态链接且被去除符号的库函数,IDA会用签名匹配IDA数据库中的函数,如果匹配上会自动重命名函数。通过实例演示整个流程

制作过程签名恢复符号表使用的样例代码。(包含标准库中多个测试函数)

//
// Created by js-v on 2022/12/7.
//
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


int main()
{
    printf("函数开始执行!!!");
    printf("hello-world!");
    char str1[15];
    char str2[15];
    int ret;
    strcpy(str1, "abcdef");
    strcpy(str2, "ABCDEF");
    ret = memcmp(str1, str2, 5);
    printf("strcpy,memcmp函数被使用ret=%d。",ret);

    const char dest[] = "oldstring";
    const char src[]  = "newstring";
    printf("Before memmove dest = %s, src = %s\n", dest, src);
    memmove(dest, src, 10);
    printf("After memmove dest = %s, src = %s\n", dest, src);

    char buffer[50];
    char* s = "runoobcom";
    // 读取字符串并存储在 buffer 中
    int j = snprintf(buffer, 6, "%s\n", s);
    // 输出 buffer及字符数
    printf("string:\n%s\ncharacter count = %d\n", buffer, j);

    char str3[80];
    sprintf(str3, "Pi 的值 = %s", s);
    printf("函数sprinf已经被执行输出字符串%s。",str3);


    int day, year;
    char weekday[20], month[20], dtm[100];
    strcpy( dtm, "Saturday March 25 1989" );
    sscanf( dtm, "%s %s %d  %d", weekday, month, &day, &year );
    printf("%s %d, %d = %s\n", month, day, year, weekday );

    char str4[] = "This is source";
    char str5[] = "This is destination";
    strcat(str5, str4);
    printf("最终的目标字符串: |%s|", str5);

    char str6[15];
    char str7[15];
    int ret2;
    strcpy(str6, "abcdef");
    strcpy(str7, "ABCDEF");
    ret2 = strncmp(str6, str7, 4);
    printf("函数strncmp已经执行ret2的结果=%n",ret2);

    char str8[30] = "2030300 This is test";
    char *ptr1;
    long ret3;
    ret3 = strtol(str8, &ptr1, 10);
    printf("strtol函数已经执行-数字(无符号长整数)是 %ld\n", ret3);
    printf("字符串部分是 |%s|", ptr1);

    char *ptr2;
    long ret6;
    ret6 = strtoul(str8, &ptr2, 10);
    printf("strtoul函数已经执行-数字(无符号长整数)是 %lu\n", ret6);
    printf("字符串部分是 |%s|", ptr2);


    const char str9[] = "http://www.runoob.com";
    const char ch = '.';
    char *ret4;
    char *ret5;
    ret4 = strchr(str9, ch);
    printf("函数strchr已经执行-|%c| 之后的字符串是 - |%s|\n", ch, ret4);
    ret5 = strrchr(str9, ch);
    printf("函数strrchr已经执行-|%c| 之后的字符串是 - |%s|\n", ch, ret5);


    char str10[50];
    int len;
    strcpy(str10, "This is runoob.com");
    len = strlen(str10);
    printf("函数strlen已经执行-|%s| 的长度是 |%d|\n", str10, len);

    char str11[50];

    strcpy(str11,"This is string.h library function");
    printf("函数memset已经执行---------");
    puts(str11);

    memset(str11,'$',7);
    puts(str11);
    return 0;
}

构建交叉编译环境来编译样例代码,没有交叉编译环境可以参考 使用脚本自动生成交叉编译链
image
静态编译

 ./arm-none-linux-gnueabi-gcc --static  hello.c -o hellos

去除符号

./arm-none-linux-gnueabi-strip hellos

注意:这里的去除符号使用的strip一定是要在交叉编译环境下的 arm-none-linux-gnueabi-strip 命令,否则会遇到如下的提示无法识别文件的错误,可以看到默认使用的是本机的strip命令。
image

使用命令查看去除符号表之后静态连接的文件。
image

使用IDA打开编译后的文件,可以看见函数名称已经不能够正常的被识别。
image

这里以交叉编译环境下的libc.a这个静态库为例制作并应用IDA签名

  1. 获取libc.a(libc的静态库),一般在交叉编译环境中的lib目录,使用find、grep命令查找即可。
  2. 下载FLAIR 插件(工具包),使用pelf(pattern)根据libc.a 创建模版文件。
./pelf libc.a libc-demo.pat

image

  1. 根据pat模版文件,制作签名文件。-n代表注释。注意,制作签名文件时,看你存在冲突,修改一下冲突的一个文件(libc-demo.exc),如果有两个以上的冲突,选择要的那一个,前面输入+即可,修改exc文件之后再次./sigmake。
  2. 复制sig文件到 IDA安装目录下sig/arm的目录下。打开IDA 加载编译好的文件的页面, shift+F5,右键添加新的签名文件。

image

可以在IDA中看见使用签名已经识别出了751个函数,左侧淡蓝色背景的函数,都是签名所识别出来的。

posted @ 2022-12-13 21:52  Satoris  阅读(104)  评论(0)    收藏  举报