【C语言】十六进制形式输出应用程序

1、前言

最近在看到同事写了一款封印病毒的程序,非常有意思!原理大致是将PE文件中的ASCII转换成HEX输出到文本中。这样做的目的是为了保存病毒样本的时候不会被杀毒软件查杀!然而却是delphi写的,特别想用C语言自己也实现一个,于是从google翻出了此代码。

2、编译后的结果

549050-20171106234711919-993602895.png

3、代码实现原理

为了兼容Win32 + *nix,需要定义头文件,在读取时把【\r\n】和【\n】区分。

// 20171105_bin2hex.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>

//Win32 + *nix
#ifdef WIN32
#define CRLF    "\r\n"
#else
#define CRLF    "\n"
#endif

//number of bytes per line
#define LINELEN     16

void printFileAsHex(FILE* file);
char toVisibleCharacter(int byteVal);
void writeLine(char* lineBuffer, int buflen);
char upperToHex(int byteVal);
char lowerToHex(int byteVal);
char nibbleToHex(int nibble);


int main(int argc, const char* argv[])
{
    FILE* file;

    //if (argc != 2)
    //{
    //  printf("Usage: phex <file>");
    //  printf(CRLF);
    //  return 1;
    //}

    // 读写文件
    file = fopen("D:\\20171111-test.exe", "rb");  //打开文件
    if (NULL == file)
    {
        printf("Cannot open %s", argv[1]);
        printf(CRLF);
        return 2;
    }

    printFileAsHex(file);

    fclose(file);

    system("pause");
    return 0;
}
//主要实现函数
void printFileAsHex(FILE* file)
{
    int count = 0;
    char buffer[LINELEN];                 //临时存放字符的数组

    while (1)
    {
        
        int byteVal = fgetc(file);        //指向的文件中读取一个字符,读取一个字节后,光标位置后移一个字节。
        
        if (EOF == byteVal)               //如果文件已经到尾部跳出循环
        {
            break;
        }
        
        buffer[count] = byteVal;          //将文件字符存储到数组中
        count++;                          //计算每个字符的数目
        
        if (count >= LINELEN)             //提前处理前16个字节
        {
            writeLine(buffer, LINELEN);
            count = 0;
        }
    }

    if (count > 0)                           //不满16字节的情况处理
    {
        writeLine(buffer, count);
    }
}

char toVisibleCharacter(int byteVal)
{
    if (byteVal >= 32 && byteVal <= 126)  // 输出可打印字符
    {
        return (char)byteVal;
    }

    return '_';                           //不可打印就输出_号
}

void writeLine(char* lineBuffer, int buflen)
{
    int i;

    char str[LINELEN];

    // 读写文件
    FILE* file = fopen("D:\\20171111-test.txt", "a+");

    for (i = 0; i < buflen; i++)
    {
        char chu = upperToHex(lineBuffer[i]); //取高4位  -->处理成十进制的值
        char chl = lowerToHex(lineBuffer[i]); //取低4位  -->处理成十进制的值
        printf("%c%c ", chu, chl);
        //自增加的-写文件到txt
        sprintf(str, "%c%c", chu, chl);
        fseek(file, 0, SEEK_END);
        fwrite(str, strlen(str), 1, file);
    }
    fclose(file);

    if (buflen < LINELEN)
    {
        for (i = LINELEN - buflen; i > 0; i--)
        {
            printf("   ");
        }
    }

    printf("\t");



    char str1[LINELEN];
    for (i = 0; i < buflen; i++)
    {
        char ch = toVisibleCharacter(lineBuffer[i]);
        printf("%c", ch);
    }

    printf(CRLF);
}

char upperToHex(int byteVal)
{
    int i = (byteVal & 0xF0) >> 4;  //0F二进制为00001111,低四位保留,然后右移4位,也就是只取出高4位的意思
    return nibbleToHex(i);
}

char lowerToHex(int byteVal)
{
    int i = (byteVal & 0x0F);  //保留低4位00001111,这次没有右移,所以保留低4位
    return nibbleToHex(i);
}

char nibbleToHex(int nibble)
{
    const int ascii_zero = 48;
    const int ascii_a = 65;

    if ((nibble >= 0) && (nibble <= 9))
    {
        return (char)(nibble + ascii_zero);   // 十六进制转换成十进制 返回数字,本来是int型,强转成char了
    }
    if ((nibble >= 10) && (nibble <= 15))
    {
        return (char)(nibble - 10 + ascii_a); // 十六进制转换成十进制的字母,本来是int型,强转成char了
    }
    return '?';                               //其余情况返回'?'
}

4、参考

  • C++ 读取PE文件并十六进制打印输出

http://blog.csdn.net/lileiyang12/article/details/19304297

  • C: hex dump application

http://illegalargumentexception.blogspot.jp/2008/05/c-hex-dump-application.html

转载于:https://www.cnblogs.com/17bdw/p/7795945.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值