环境:OS X 10.12.4
抱歉,本文章并不是关于Ollydbg的实现(笑)。
照旧man 1 od
。
od
是一个能把指定的文件或者标准输入按照用户定义的格式打印。(
The od utility is a filter which displays the specified files,or standard input if no files are specified,in a user specified format.)
乍一看这个命令的参数有一大堆,本文只挑一部分去实现,包括-A
指定地址基数,-j
跳过指定数目的字符,-N
最多打印n个字符。-t
输出格式。
实现起来并不难,只是参数比较多,实现起来比较繁琐,同样可以使用前面写的xc_file.c
缓存输入。
od.c 不完全实现,BUG N多
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <limits.h>
enum{
DEC,HEX,OCT,NOADDR
}addr_base,output_format;
void xc_open(char *aFName);
void xc_readFromStdin(void);
int xc_getchar(void);
void xc_close(void);
void xc_moveto(int offset,int whence);
void print_char(int ch,int size);
void print_addr(int addr);
void format_error(void);
int dump_bytes(char *str);
/* Usage: od [-A base] [-j skip] [-N length] [-t type] [file] */
/* default for od -t o2 [file] if no option is given */
int main(int ac,char *av[])
{
addr_base = OCT;
int skip = 0;
int length = INT_MAX;
int cnt = 0;
int size = 2; /* output size */
int i,j;
int end_print = 0;
int bytes_print;
output_format = OCT;
while(--ac && (*++av)[0] == '-'){
switch(*++av[0]){
case 'A':
switch((*++av)[0]){
case 'd':
addr_base = DEC;
break;
case 'o':
break;
case 'x':
addr_base = HEX;
break;
case 'n':
addr_base = NOADDR;
break;
default:
format_error();
}
--ac; /* substract because read a option value */
break;
case 'j':
skip = dump_bytes(*++av);
if(skip <= 0)
format_error();
--ac; /* substract because read a option value */
break;
case 'N':
length = atoi(*++av);
if(length <= 0)
format_error();
--ac; /* substract because read a option value */
break;
case 't':
switch((*++av)[0]){
case 'd': /* signed decimal */
case 'u': /* unsigned decimal */
/* do not reconize signed or unsigned */
output_format = DEC;
break;
case 'o': /* octal */
output_format = OCT;
break;
case 'x': /* hexadecimal */
output_format = HEX;
break;
default:
format_error();
}
switch(*++av[0]){
case 'C':
size = sizeof(char);
break;
case 'S':
size = sizeof(short);
break;
case 'I':
size = sizeof(int);
break;
case 'L':
size = sizeof(long);
break;
default:
if(*av[0] >= '0' && *av[0] <= '9')
{
size = atoi(av[0]);
if(size <= 0)
format_error();
}else
format_error();
break;
}
--ac; /* substract because read a option value */
break;
}
}
if(ac == 1)
xc_open(*av);
else
xc_readFromStdin();
/* default `skip` is zero if `-j` option is not given */
xc_moveto(skip,SEEK_SET);
cnt = skip;
while(cnt < length && !end_print){
int size_count = 0;
int buf[sizeof(long)];
int tmpValue = 0;
int ch;
print_addr(cnt);
while(cnt < length && !end_print){
size_count = 0;
while(size_count < size && cnt < length && (ch = xc_getchar()) != EOF){
buf[size_count++] = ch;
cnt++;
}
tmpValue = 0;
for(i = size_count - 1; i >= 0; --i)
tmpValue = tmpValue * 256 + buf[i];
print_char(tmpValue,size);
if(ch == EOF || cnt == length){
// int tmp = cnt;
// while(++tmp % 16)
// ;
// tmp = (tmp - cnt) / size;
// while(tmp--)
// print_char(' ',size);
end_print = 1;
while(++cnt % 16)
;
}
if(cnt % 16 == 0){
/* 16 bytes per line */
printf("\n");
break;
}
}
}
print_addr(cnt);
printf("\n");
xc_close();
return 0;
}
void print_char(int ch,int size)
{
switch(output_format){
case OCT:
switch(size){
case 1:
printf(" %.3o",ch);
break;
case 2:
printf(" %.6o",ch);
break;
case 4:
break;
}
break;
case DEC:
printf("%d ",ch);
break;
case HEX:
printf("%x ",ch);
break;
}
}
void print_addr(int addr)
{
switch(addr_base){
case OCT:
printf("%.7o ",addr);
break;
case HEX:
printf("%.7x ",addr);
break;
case DEC:
printf("%.7d ",addr);
break;
case NOADDR:
printf("%7.7s "," ");
break;
}
}
int dump_bytes(char *str)
{
int ans = 0;
while(*str >= '0' && *str <= '9'){
ans = ans * 10 + (*str - '0');
str++;
}
switch(*str){
case '\0':
break;
case 'b': /* block(512 bytes) */
ans *= 512;
break;
case 'k': /* kilobyte */
ans *= 1024;
break;
case 'm': /* megabyte */
ans *= 1024 * 1024;
break;
}
return ans;
}
void format_error(void)
{
fprintf(stderr,"Usage: od [-A base] [-j skip] [-N length] [-t type] [file]\n");
exit(1);
}
xc_file.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
/* BUFSIZ define in stdio.h,commonly is 1024 */
static unsigned char chBuf[BUFSIZ];
static int fd = -1;
static char fName[BUFSIZ];
static int chCur;
static int chSum;
void xc_readFromStdin(void)
{
/* define in unistd.h */
fd = STDIN_FILENO;
}
void xc_open(char *aFName)
{
if((fd = open(aFName,O_RDONLY)) == -1){
perror(aFName);
exit(1);
}
strcpy(fName,aFName); /* record which file is opened */
chCur = chSum = 0;
}
int xc_reload(void)
{
int bytes_read;
if((bytes_read = read(fd,chBuf,BUFSIZ)) > 0){
chCur = 0;
chSum = bytes_read;
return chBuf[chCur++];
}else if(bytes_read == -1){
perror(fName);
exit(1);
}else if (bytes_read == 0)
return EOF;
}
int xc_getchar(void)
{
if(fd == -1)
return EOF;
if(chSum == chCur)
return xc_reload();
return chBuf[chCur++];
}
void xc_close(void)
{
if(fd != -1)
{
if(close(fd) == -1){
perror(fName);
exit(1);
}
fd = -1;
}
}
void xc_moveto(int offset,int whence)
{
if(fd == -1)
return ;
if(lseek(fd,offset,whence) == -1){
perror("target position are illegal");
exit(1);
}
}