Xplay 发表于 2021-3-14 09:48

自定义一款软件的初始化logo

自定义一款软件的初始化logo

环境

系统:Windows Ubuntu
工具:HxD.exe
软件:xray_linux_amd64

问题

将工具的初始化logo(图1)替换为另一个logo(图2)




思路

1、在16进制编辑器中找到logo数据所在的位置,然后手动修改16进制数值即可。
2、脚本提取新的logo的16进制数据,将数据写入到二进制文件的指定位置即可。

分析

首先想到的就是这些logo其实就是存储在程序中的字符串,所以通过搜索字符串对其定位,然后
将数据替换即可,在替换数据前要考虑到替换后的数据是否会覆盖掉logo后面的数据,从而可能
影响正常使用。

1、手动修改
搜索字符串,如图:

定位到字符串所在位置,如下图所示:

然后一个一个字节修改其数据即可。

PS:这段数据映射到内存中的虚拟地址为0x400000(基地址) + 0x14029E4 = 0x18029E4,可以看到
这段数据在程序的.rodata段,如下图所示:


2、使用脚本修改logo
首先是提取自定义图标的16进制数据,使用python脚本提取,代码如data.py。

提取数据代码:data.py
import os
def logo():
    a = """
    _         _               __
   / \_   _| |_ ____ __/ _|
/ _ \| | | | __/ _ \| '_ \| |_
/ ___ \ |_| | || (_) | |_) |_|
/_/   \_\__,_|\__\___/| .__/|_|
                      |_|
    """
    for index in range(len(a)):
      # 16进制输出 ==> print('%#x '%ord(a),end='')
      #16进制格式打印,并且补齐两位,不足两位以'0'补齐
      print("0x%02x " % ord(a),end='')
      if ((index+1) % 10) == 0:
            print()
    #获取logo长度,这样就知道修改之后要填充多少数据
    print(len(a))
    os.system("pause")
def main():
    logo()
if __name__ == '__main__':
    main()

提取logo的数据如下图:


往二进制文件写入数据,用到一些设置文件流指针位置的函数。刚打开文件会指向开头位置,然后
加上我们要修改位置的偏移,然后开始写入数据即可,最后切记关闭文件流。

修改logo代码:logo.c
#include <stdio.h>
#include<windows.h>
//要替换的logo长度 201
BYTE sByte[] = {
0x0a ,0x20 ,0x20 ,0x20 ,0x20 ,0x5f ,0x20 ,0x20 ,0x20 ,0x20
,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x5f ,0x20 ,0x20 ,0x20 ,0x20
,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20
,0x20 ,0x5f ,0x5f ,0x20 ,0x0a ,0x20 ,0x20 ,0x20 ,0x2f ,0x20
,0x5c ,0x20 ,0x20 ,0x5f ,0x20 ,0x20 ,0x20 ,0x5f ,0x7c ,0x20
,0x7c ,0x5f ,0x20 ,0x5f ,0x5f ,0x5f ,0x20 ,0x20 ,0x5f ,0x20
,0x5f ,0x5f ,0x20 ,0x20 ,0x2f ,0x20 ,0x5f ,0x7c ,0x0a ,0x20
,0x20 ,0x2f ,0x20 ,0x5f ,0x20 ,0x5c ,0x7c ,0x20 ,0x7c ,0x20
,0x7c ,0x20 ,0x7c ,0x20 ,0x5f ,0x5f ,0x2f ,0x20 ,0x5f ,0x20
,0x5c ,0x7c ,0x20 ,0x27 ,0x5f ,0x20 ,0x5c ,0x7c ,0x20 ,0x7c
,0x5f ,0x20 ,0x0a ,0x20 ,0x2f ,0x20 ,0x5f ,0x5f ,0x5f ,0x20
,0x5c ,0x20 ,0x7c ,0x5f ,0x7c ,0x20 ,0x7c ,0x20 ,0x7c ,0x7c
,0x20 ,0x28 ,0x5f ,0x29 ,0x20 ,0x7c ,0x20 ,0x7c ,0x5f ,0x29
,0x20 ,0x7c ,0x20 ,0x20 ,0x5f ,0x7c ,0x0a ,0x2f ,0x5f ,0x2f
,0x20 ,0x20 ,0x20 ,0x5c ,0x5f ,0x5c ,0x5f ,0x5f ,0x2c ,0x5f
,0x7c ,0x5c ,0x5f ,0x5f ,0x5c ,0x5f ,0x5f ,0x5f ,0x2f ,0x7c
,0x20 ,0x2e ,0x5f ,0x5f ,0x2f ,0x7c ,0x5f ,0x7c ,0x20 ,0x20
,0x0a ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20
,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20 ,0x20
,0x20 ,0x20 ,0x20 ,0x7c ,0x5f ,0x7c ,0x0a ,0x20 ,0x20 ,0x20
,0x20};
//手动计算要写入的数据,还不能完全覆盖原始的logo,所以此处要有填充数据
//0x1402AD6 - 0x14029E4 + 0x1 - 0xC9 =0x2A
BYTE nop;
int main()
{
    fpos_t filepos;
    BYTE cByte;
    int i;
    //"rb+" 打开一个二进制文件,文件必须存在,允许读写
    FILE *stream = fopen("G:\\xray_linux_amd64","rb+");
    //首先得到文件指针的起始位置; %X表示16进制大写输出
    fgetpos(stream,&filepos);
    printf("Current filepos:%X\n",filepos);

    //手动找到要修改的偏移位置
    filepos = filepos + 0x14029E4;

    /*
    使用feek将文件指针移动到偏移的位置,偏移起始位置:
    文件头0(SEEK_SET),
    当前位置1(SEEK_CUR),
    文件尾2(SEEK_END)
    fseek(stream,filepos,SEEK_SET);
    */
    //使用fsetpos设置文件指针位置
    fsetpos(stream,&filepos);
    printf("After set Filepos:%X\n",filepos);

    //读取偏移位置处的字节是否正确,每次读取一个字节,最多读取两个
    fread(cByte,1,2,stream);
    printf("Read Byte: %X %X\n",cByte,cByte);

    //再次确认当前数据流位置是否正确,此时filepos比前面+2,所以fread是会移动文件指针的
    fgetpos(stream,&filepos);
    printf("Current filepos:%X\n",filepos);

    //由于前面移动了文件指针,此处再-2,然后重新设置文件指针位置
    filepos = filepos - 2;
    fsetpos(stream,&filepos);

    //重新设置好偏移位置后,写入数据,每次写入一个字节
    fwrite(sByte,strlen(sByte),1,stream);

    //写入填充数据
    for(i = 0;i < 0x2A;i++)
    {
      nop = (BYTE)0x20;
    }
    fwrite(nop,strlen(nop),1,stream);

    //写入数据完成后指针的位置
    fgetpos(stream,&filepos);
    printf("End filepos:%X\n",filepos);

    fclose(stream);
    return 0;
}

修改后的程序运行效果如下图:



页: [1]
查看完整版本: 自定义一款软件的初始化logo