1、前言

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

2、编译后的结果

3、代码实现原理

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

  1. // 20171105_bin2hex.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. //Win32 + *nix
  7. #ifdef WIN32
  8. #define CRLF "\r\n"
  9. #else
  10. #define CRLF "\n"
  11. #endif
  12. //number of bytes per line
  13. #define LINELEN 16
  14. void printFileAsHex(FILE* file);
  15. char toVisibleCharacter(int byteVal);
  16. void writeLine(char* lineBuffer, int buflen);
  17. char upperToHex(int byteVal);
  18. char lowerToHex(int byteVal);
  19. char nibbleToHex(int nibble);
  20. int main(int argc, const char* argv[])
  21. {
  22. FILE* file;
  23. //if (argc != 2)
  24. //{
  25. // printf("Usage: phex <file>");
  26. // printf(CRLF);
  27. // return 1;
  28. //}
  29. // 读写文件
  30. file = fopen("D:\\20171111-test.exe", "rb"); //打开文件
  31. if (NULL == file)
  32. {
  33. printf("Cannot open %s", argv[1]);
  34. printf(CRLF);
  35. return 2;
  36. }
  37. printFileAsHex(file);
  38. fclose(file);
  39. system("pause");
  40. return 0;
  41. }
  42. //主要实现函数
  43. void printFileAsHex(FILE* file)
  44. {
  45. int count = 0;
  46. char buffer[LINELEN]; //临时存放字符的数组
  47. while (1)
  48. {
  49. int byteVal = fgetc(file); //指向的文件中读取一个字符,读取一个字节后,光标位置后移一个字节。
  50. if (EOF == byteVal) //如果文件已经到尾部跳出循环
  51. {
  52. break;
  53. }
  54. buffer[count] = byteVal; //将文件字符存储到数组中
  55. count++; //计算每个字符的数目
  56. if (count >= LINELEN) //提前处理前16个字节
  57. {
  58. writeLine(buffer, LINELEN);
  59. count = 0;
  60. }
  61. }
  62. if (count > 0) //不满16字节的情况处理
  63. {
  64. writeLine(buffer, count);
  65. }
  66. }
  67. char toVisibleCharacter(int byteVal)
  68. {
  69. if (byteVal >= 32 && byteVal <= 126) // 输出可打印字符
  70. {
  71. return (char)byteVal;
  72. }
  73. return '_'; //不可打印就输出_号
  74. }
  75. void writeLine(char* lineBuffer, int buflen)
  76. {
  77. int i;
  78. char str[LINELEN];
  79. // 读写文件
  80. FILE* file = fopen("D:\\20171111-test.txt", "a+");
  81. for (i = 0; i < buflen; i++)
  82. {
  83. char chu = upperToHex(lineBuffer[i]); //取高4位 -->处理成十进制的值
  84. char chl = lowerToHex(lineBuffer[i]); //取低4位 -->处理成十进制的值
  85. printf("%c%c ", chu, chl);
  86. //自增加的-写文件到txt
  87. sprintf(str, "%c%c", chu, chl);
  88. fseek(file, 0, SEEK_END);
  89. fwrite(str, strlen(str), 1, file);
  90. }
  91. fclose(file);
  92. if (buflen < LINELEN)
  93. {
  94. for (i = LINELEN - buflen; i > 0; i--)
  95. {
  96. printf(" ");
  97. }
  98. }
  99. printf("\t");
  100. char str1[LINELEN];
  101. for (i = 0; i < buflen; i++)
  102. {
  103. char ch = toVisibleCharacter(lineBuffer[i]);
  104. printf("%c", ch);
  105. }
  106. printf(CRLF);
  107. }
  108. char upperToHex(int byteVal)
  109. {
  110. int i = (byteVal & 0xF0) >> 4; //0F二进制为00001111,低四位保留,然后右移4位,也就是只取出高4位的意思
  111. return nibbleToHex(i);
  112. }
  113. char lowerToHex(int byteVal)
  114. {
  115. int i = (byteVal & 0x0F); //保留低4位00001111,这次没有右移,所以保留低4位
  116. return nibbleToHex(i);
  117. }
  118. char nibbleToHex(int nibble)
  119. {
  120. const int ascii_zero = 48;
  121. const int ascii_a = 65;
  122. if ((nibble >= 0) && (nibble <= 9))
  123. {
  124. return (char)(nibble + ascii_zero); // 十六进制转换成十进制 返回数字,本来是int型,强转成char了
  125. }
  126. if ((nibble >= 10) && (nibble <= 15))
  127. {
  128. return (char)(nibble - 10 + ascii_a); // 十六进制转换成十进制的字母,本来是int型,强转成char了
  129. }
  130. return '?'; //其余情况返回'?'
  131. }

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. 评审other's意见

    评审意见 1.组 a.界面不友好 b.没连数据库 2.组 a.没连数据库 b.无智能匹配当前时间 3.组 a.基本功能实现 b.界面未优化 4.组 ourselves 5.组 a.各反面较为完善 6. ...

  2. Day Eight

    站立式会议 站立式会议内容总结 331 今天:学习树状自关联 hibernate配置,查询 详情:http://blog.csdn.net/u011644423/article/details/498 ...

  3. 第二个Sprint冲刺第 八天(燃尽图)

    因为今天停电了,所以我们也休息一天!

  4. [转帖] 学习 Linux 大页的内存知识

    一.在解释什么情况下需要开启大页和为啥需要开启大页前先了解下Linux下页的相关的知识:以下的内容是基于32位的系统,4K的内存页大小做出的计算1)目录表,用来存放页表的位置,共包含1024个目录en ...

  5. 【Java并发编程】之十五:并发编程中实现内存可见的两种方法比较:加锁和volatile变量

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17290021 在http://blog.csdn.net/ns_code/article/ ...

  6. 【BZOJ3745】Norma(CDQ分治)

    [BZOJ3745]Norma(CDQ分治) 题面 BZOJ 洛谷 题解 这种问题直接做不好做,显然需要一定的优化.考虑\(CDQ\)分治. 现在唯一需要考虑的就是跨越当前中间节点的所有区间如何计算答 ...

  7. 51nod1229 序列求和 V2 【数学】

    题目链接 B51nod1229 题解 我们要求 \[\sum\limits_{i = 1}^{n}i^{k}r^{i}\] 如果\(r = 1\),就是自然数幂求和,上伯努利数即可\(O(k^2)\) ...

  8. Python OS模块中的fork方法实现多进程

    import os '''使用OS模块中的fork方式实现多进程''' '''fork方法返回两次,分别在父进程和子进程中返回,子进程中永远返回0,父进程返回的是子进程的is''' if __name ...

  9. POJ 3159 Candies (图论,差分约束系统,最短路)

    POJ 3159 Candies (图论,差分约束系统,最短路) Description During the kindergarten days, flymouse was the monitor ...

  10. 函数和常用模块【day05】:生成器并行计算(五)

    本节内容 1.概述 2.生成器执行原理 3.send()和__next__()方法的区别 4.yield实现并行效果 一.概述 之前只是介绍生成器,那有些同学就说了,这个生成器除了能节省资源,提高工作 ...