1、前言

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

2、编译后的结果

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

【C语言】十六进制形式输出应用程序的更多相关文章

  1. 把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列。

    编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列. 实现了unsigned long型的转换. // 十进制转换为二进制,十进制数的每1bit转换为二进制的1 ...

  2. C语言 printf格式化输出,参数详解

      有关输出对齐 int main(int argc, char* argv[]){ char insertTime[20] = {"1234567890"}; double in ...

  3. c语言 printf格式化输出

    #include <iostream> #include<stdio.h> #include <cstring> using namespace std; int ...

  4. 【C语言】- 数据输出-printf( )和putchar( )

    格式化输出函数printf( ) printf( )功能: 向系统指定输出设备按指定的格式输入任意个任意类型的数据,并返回实际输出的字符数.若出错,将返回负数. printf( )使用形式: prin ...

  5. C语言中以字符串形式输出枚举变量

    C语言中以字符串形式输出枚举变量 摘自:https://blog.csdn.net/haifeilang/article/details/41079255 2014年11月13日 15:17:20 h ...

  6. xxd - 以十六进制形式表示

    总览 (SYNOPSIS) xxd -h[elp] xxd [options] [infile [outfile]] xxd -r[evert] [options] [infile [outfile] ...

  7. C语言之一天一个小程序

    程序示例: #include <stdio.h> #include <stdlib.h> int main() { printf("Hello,world!\n&qu ...

  8. [Windows] [VS] [C] [取得指针所指内存的十六进制形式字符串]

    接口定义如下: #include <Windows.h> // 取得指针所指内存的十六进制形式字符串,size指定字节长度 #define Mem_toString(address, si ...

  9. 统计一个16位二进制数中1的个数,并将结果以十六进制形式显示在屏幕上,用COM格式实现。

    问题 统计一个16位二进制数中1的个数,并将结果以十六进制形式显示在屏幕上,用COM格式实现. 代码 code segment assume cs:code org 100h main proc ne ...

随机推荐

  1. 冲刺Two之站立会议1

    今天我们开始了第二个冲刺期的工作,大家重新讨论了下个阶段的工作内容,由于上次演示我们主要只是实现了摄像头开启.通信和语音通话的功能,而且各部分还有待完善.所以我们决定了之后的主要工作的内容:之前服务器 ...

  2. 剑指offer:合并两个排序的链表

    题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解题思路: 这道题应该考察也是链表的相关操作.具体实现,新建一个新的链表,用两个指针分别指向两 ...

  3. 什么是GPS的冷启动、温启动和热启动?

    对于GPS多种启动方式的概念还很模糊,冷启动.热启动.温启动各种专业术语铺天盖地,使得许多用户眼花缭乱. 我们简单从定义上了解一下几种GPS启动的方式,GPS开机启动分为冷启动.温启动.热启动三种. ...

  4. Magical Girl Haze 南京网络赛2018

    题意: 就是使不大于k条路的权值变为零后求最短路 解析: d[i][j]表示使j条路变为权值后从起点到点i的最短路径 这题不能用spfa做  tle #include <iostream> ...

  5. 【题解】 Luogu P1402 酒店之王 (二分图匹配)

    懒得复制,原题目戳我 Solution: 这题没想到这么水,就是两个二分图而已 如果房间的二分图没匹配成功就直接进入下一个人 如果房间的二分图匹配成功,食物二分图匹配不成功就把房间的\(be[ ]\) ...

  6. 【bzoj4516】 Sdoi2016—生成魔咒

    http://www.lydsy.com/JudgeOnline/problem.php?id=4516 (题目链接) 题意 依次向字符串末尾加上一个字符,每次求不同子串个数. Solution 如果 ...

  7. 前端学习 -- Css -- 高度坍塌问题的产生以及解决

    在文档流中,父元素的高度默认是被子元素撑开的,也就是子元素多高,父元素就多高. 但是当为子元素设置浮动以后,子元素会完全脱离文档流,此时将会导致子元素无法撑起父元素的高度,导致父元素的高度塌陷. 由于 ...

  8. Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流)

    Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流) Description 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. ...

  9. 浅谈使用NIO,AIO的感受

    花了十多天的时间把原来的WEB服务由BIO(阻塞IO)模式改写成NIO(非阻塞IO)模式,然后在xp机子上用ab测试并发性能,确实提升了30%左右的并发性能,测试完成后,当时感觉还是挺满意的.几天前在 ...

  10. UDP ------ UDP Broadcast Address

    Related information link : 百度百科---->广播地址 Use restrictions: 1. You can only broadcast on the same ...