【C语言】十六进制形式输出应用程序
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语言】十六进制形式输出应用程序的更多相关文章
- 把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列。
编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列. 实现了unsigned long型的转换. // 十进制转换为二进制,十进制数的每1bit转换为二进制的1 ...
- C语言 printf格式化输出,参数详解
有关输出对齐 int main(int argc, char* argv[]){ char insertTime[20] = {"1234567890"}; double in ...
- c语言 printf格式化输出
#include <iostream> #include<stdio.h> #include <cstring> using namespace std; int ...
- 【C语言】- 数据输出-printf( )和putchar( )
格式化输出函数printf( ) printf( )功能: 向系统指定输出设备按指定的格式输入任意个任意类型的数据,并返回实际输出的字符数.若出错,将返回负数. printf( )使用形式: prin ...
- C语言中以字符串形式输出枚举变量
C语言中以字符串形式输出枚举变量 摘自:https://blog.csdn.net/haifeilang/article/details/41079255 2014年11月13日 15:17:20 h ...
- xxd - 以十六进制形式表示
总览 (SYNOPSIS) xxd -h[elp] xxd [options] [infile [outfile]] xxd -r[evert] [options] [infile [outfile] ...
- C语言之一天一个小程序
程序示例: #include <stdio.h> #include <stdlib.h> int main() { printf("Hello,world!\n&qu ...
- [Windows] [VS] [C] [取得指针所指内存的十六进制形式字符串]
接口定义如下: #include <Windows.h> // 取得指针所指内存的十六进制形式字符串,size指定字节长度 #define Mem_toString(address, si ...
- 统计一个16位二进制数中1的个数,并将结果以十六进制形式显示在屏幕上,用COM格式实现。
问题 统计一个16位二进制数中1的个数,并将结果以十六进制形式显示在屏幕上,用COM格式实现. 代码 code segment assume cs:code org 100h main proc ne ...
随机推荐
- Linux内核分析 笔记三 构造一个简单的Linux系统MenuOS ——by王玥
一.知识点总结 (一)Linux源代码简介 arch/x86目录下的代码是我们重点关注的 内核启动相关代码都在init目录下 start_kernel函数相当于普通C程序的main函数 linux的核 ...
- 第二个spring冲刺第9天
其中一个队员在检查程序的BUG途中发现了几个重要的BUG比如答案乱码.程序闪退,弹出黑幕.于是我们决定先把这些问题解决再继续开发其他功能
- 2017-8-20 HTTP协议
http协议 http协议是一种超文本传输协议(一种约定) 三大特性:无状态,媒体独立,无连接: HTTP 工作原理 HTTP协议工作于客户端-服务端架构为上.浏览器作为HTTP客户端通过URL向HT ...
- DOM之节点类型加例子
DOM= Document Object Model,文档对象模型,DOM可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构.换句话说,这是表示和处理一个HTML或XML文档的常用方法.D ...
- 使用alpine的docker镜像下 dind 的方式安装dotnet core 的一个非dockerfile的方法
1. 下载dind的镜像 docker pull docker:dind 2. 执行该镜像 docker run -it --privileged --name some-docker -d dock ...
- js 复制到剪切板
function copyTextToClipboard(text) { var copyFrom = $('<textarea/>'); copyFrom.text(text); $(' ...
- 用jq获取元素内文本,但不包括其子元素内的文本值的方法
<li id="listItem"> This is some text <span id="firstSpan">First span ...
- 洛谷P4720 【模板】扩展卢卡斯
P4720 [模板]扩展卢卡斯 题目背景 这是一道模板题. 题目描述 求 C(n,m)%P 其中 C 为组合数. 输入输出格式 输入格式: 一行三个整数 n,m,p ,含义由题所述. 输出格式: 一行 ...
- 安装 oracle
先下载3个东西:链接忘记了,大家自己找一下 1 ORA+11+G+R2+server+64bit+for+windows.iso (oracle 安装文件) 2 PLSql 3 oracle6 ...
- 【HDU1710】树的遍历
题目大意:给定一棵 N 个节点的二叉树的前序遍历和中序遍历,求其后序遍历. 题解:递归操作,每次只需知道先序遍历和中序遍历的开始点,左子树大小即可,根据前序遍历的开始位置可知子树根节点的坐标,再在中序 ...