Skip to content

Commit

Permalink
recognize int 21h functions if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
Nico01 committed Mar 29, 2016
1 parent 56250b6 commit b4a0026
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CFLAGS = -Wall -Wextra -pedantic
CFLAGS = -Wall -Wextra -pedantic -ggdb3
LIBNAME = capstone

all: ded
Expand Down
217 changes: 204 additions & 13 deletions core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,134 @@
#include <capstone/capstone.h>
#include <inttypes.h>


char *int21h[] = {
"Terminate process", // 0x00
"Character input with echo", // 0x01
"Character output", // 0x02
"Auxiliary input", // 0x03
"Auxiliary output", // 0x04
"Printer output", // 0x05
"Direct console i/o", // 0x06
"Unfiltered char i w/o echo", // 0x07
"Character input without echo", // 0x08
"Display string", // 0x09
"Buffered keyboard input", // 0x0a
"Check input status", // 0x0b
"Flush input buffer and then input", // 0x0c
"Disk reset", // 0x0d
"Select disk", // 0x0e
"Open file", // 0x0f
"Close file", // 0x10
"Find first file", // 0x11
"Find next file", // 0x12
"Delete file", // 0x13
"Sequential read", // 0x14
"Sequential write", // 0x15
"Create file", // 0x16
"Rename file", // 0x17
"Reserved", // 0x18
"Get current disk", // 0x19
"Set DTA address", // 0x1a
"Get default drive data", // 0x1b
"Get drive data", // 0x1c
"Reserved", // 0x1d
"Reserved", // 0x1e
"Get disk parameter block for default drive", // 0x1f
"Reserved", // 0x20
"Random read", // 0x21
"Random write", // 0x22
"Get file size", // 0x23
"Set relative record number", // 0x24
"Set interrupt vector", // 0x25
"Create new PSP", // 0x26
"Random block read", // 0x27
"Random block write", // 0x28
"Parse filename", // 0x29
"Get date", // 0x2a
"Set date", // 0x2b
"Get time", // 0x2c
"Set time", // 0x2d
"Set verify flag", // 0x2e
"Get DTA address", // 0x2f
"Get MSDOS version number", // 0x30
"Terminate and stay resident", // 0x31
"Get disk parameter block for specified drive", // 0x32
"Get or set break flag", // 0x33
"Get InDOS flag pointer", // 0x34
"Get interrupt vector", // 0x35
"Get drive allocation info", // 0x36
"Get or set switch character", // 0x37
"Get or set country info", // 0x38
"Create directory", // 0x39
"Delete directory", // 0x3a
"Set current directory", // 0x3b
"Create file", // 0x3c
"Open file", // 0x3d
"Close file", // 0x3e
"Read file or device", // 0x3f
"Write file or device", // 0x40
"Delete file", // 0x41
"Set file pointer", // 0x42
"Get or set file attributes", // 0x43
"IOCTL (i/o control)", // 0x44
"Duplicate handle", // 0x45
"Redirect handle", // 0x46
"Get current directory", // 0x47
"Alloate memory block", // 0x48
"Release memory block", // 0x49
"Resize memory block", // 0x4a
"Execute program (exec)", // 0x4b
"Terminate process with return code", // 0x4c
"Get return code", // 0x4d
"Find first file", // 0x4e
"Find next file", // 0x4f
"Set current PSP", // 0x50
"Get current PSP", // 0x51
"Get DOS internal pointers (SYSVARS)", // 0x52
"Create disk parameter block", // 0x53
"Get verify flag", // 0x54
"Create program PSP", // 0x55
"Rename file", // 0x56
"Get or set file date & time", // 0x57
"Get or set allocation strategy", // 0x58
"Get extended error information", // 0x59
"Create temporary file", // 0x5a
"Create new file", // 0x5b
"Lock or unlock file region", // 0x5c
"File sharing functions", // 0x5d
"Get machine name", // 0x5e
"Device redirection", // 0x5f
"Qualify filename", // 0x60
"Reserved", // 0x61
"Get PSP address", // 0x62
"Get DBCS lead byte table", // 0x63
"Set wait for external event flag", // 0x64
"Get extended country information", // 0x65
"Get or set code page", // 0x66
"Set handle count", // 0x67
"Commit file", // 0x68
"Get or set media id", // 0x69
"Commit file", // 0x6a
"Reserved", // 0x6b
"Extended open file" // 0x6c
};


static list *list_init(uint64_t data)
{
list *l = malloc(sizeof(list));

if (l != NULL) {
l->next = NULL;
l->value = data;
l->visited = false;
}

return l;
}


static void list_add(list *node, uint64_t data)
{
list *l = node;
Expand All @@ -25,6 +141,7 @@ static void list_add(list *node, uint64_t data)
l->next = list_init(data);
}


static void list_remove_duplicates(list *node)
{
list *c1, *c2, *dup;
Expand All @@ -45,6 +162,7 @@ static void list_remove_duplicates(list *node)
}
}


static bool list_cmp_addr(list *node, uint64_t data)
{
while (node) {
Expand Down Expand Up @@ -91,6 +209,7 @@ MZ_Hdr *read_mz_header(FILE *fp)
return mz_hdr;
}


void disp_header(MZ_Hdr *mz_hdr)
{
printf("DOS Header:\n");
Expand All @@ -114,6 +233,7 @@ uint64_t get_entry(MZ_Hdr *mz_hdr)
return (mz_hdr->header_paragraphs * 16);
}


size_t get_exe_size(MZ_Hdr *mz_hdr)
{
size_t size = mz_hdr->blocks_in_file * 512 - (mz_hdr->header_paragraphs * 16);
Expand All @@ -123,6 +243,7 @@ size_t get_exe_size(MZ_Hdr *mz_hdr)
return size;
}


char *get_opcodes(cs_insn insn)
{
uint8_t len = (2 * insn.size) + 1;
Expand All @@ -139,6 +260,39 @@ char *get_opcodes(cs_insn insn)
return opcodes;
}


uint8_t get_reg_ah(cs_insn insn)
{
cs_detail *detail = insn.detail;
uint8_t reg_ah = 0xff;

if (detail->x86.op_count == 2) {
if (detail->x86.operands[0].type == X86_OP_REG && detail->x86.operands[1].type == X86_OP_IMM) {
if (detail->x86.operands[0].reg == X86_REG_AH)
reg_ah = detail->x86.operands[1].imm;

if (detail->x86.operands[0].reg == X86_REG_AX)
reg_ah = detail->x86.operands[1].imm >> 8;

return reg_ah;
}
}
return reg_ah;
}


bool is_int21h(cs_insn insn)
{
cs_detail *detail = insn.detail;

if (detail->x86.operands[0].imm == 0x21) {
return true;
}

return false;
}


list *search_call(uint64_t addr, size_t size, uint8_t *buffer)
{
csh handle;
Expand Down Expand Up @@ -177,6 +331,7 @@ list *search_call(uint64_t addr, size_t size, uint8_t *buffer)
return proc_addr;
}


list *search_jump(uint64_t addr, size_t size, uint8_t *buffer)
{
csh handle;
Expand Down Expand Up @@ -215,18 +370,22 @@ list *search_jump(uint64_t addr, size_t size, uint8_t *buffer)
return labl_addr;
}


void rt_disasm(uint64_t entry, uint64_t addr, size_t size, uint8_t *buffer, list *call, list *jump)
{
csh handle = 0;
cs_insn *insn;
const uint8_t *code = NULL;
uint8_t r_ah = 0xff;

call->visited = true;

if (cs_open(CS_ARCH_X86, CS_MODE_16, &handle) != CS_ERR_OK) {
printf("ERROR: Failed to initialize engine!\n");
exit(EXIT_FAILURE);
}

cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);

while (jump) {
Expand All @@ -239,14 +398,30 @@ void rt_disasm(uint64_t entry, uint64_t addr, size_t size, uint8_t *buffer, list

while (cs_disasm_iter(handle, &code, &size, &addr, insn)) {
char *opcodes = get_opcodes(*insn);
printf("0x%06" PRIx64 ":\t %-20s\t%s %s\n", insn->address, opcodes, insn->mnemonic, insn->op_str);
free(opcodes);

if (list_cmp_addr(jump, addr))
printf("\nlabel_0x%lx\n", addr);
if (get_reg_ah(*insn) != 0xff)
r_ah = get_reg_ah(*insn);

if (insn->id == X86_INS_INT && is_int21h(*insn) && r_ah != 0xff) {
printf("0x%06" PRIx64 ":\t %-20s\t%s %s ; %s\n", insn->address, opcodes, insn->mnemonic, insn->op_str, int21h[r_ah]);
free(opcodes);

if (list_cmp_addr(jump, addr))
printf("\nlabel_0x%lx\n", addr);

if (list_cmp_addr(call, addr))
goto end;
}
else {
printf("0x%06" PRIx64 ":\t %-20s\t%s %s\n", insn->address, opcodes, insn->mnemonic, insn->op_str);
free(opcodes);

if (list_cmp_addr(jump, addr))
printf("\nlabel_0x%lx\n", addr);

if (list_cmp_addr(call, addr))
goto end;
if (list_cmp_addr(call, addr))
goto end;
}
}
cs_free(insn, 1);
}
Expand All @@ -259,14 +434,29 @@ void rt_disasm(uint64_t entry, uint64_t addr, size_t size, uint8_t *buffer, list

while (cs_disasm_iter(handle, &code, &size, &addr, insn)) {
char *opcodes = get_opcodes(*insn);
printf("0x%06" PRIx64 ":\t %-20s\t%s %s\n", insn->address, opcodes, insn->mnemonic, insn->op_str);
free(opcodes);
if (get_reg_ah(*insn) != 0xff)
r_ah = get_reg_ah(*insn);

if (list_cmp_addr(jump, addr))
printf("\nlabel_0x%lx\n", addr);
if (insn->id == X86_INS_INT && is_int21h(*insn) && r_ah != 0xff) {
printf("0x%06" PRIx64 ":\t %-20s\t%s %s ; %s\n", insn->address, opcodes, insn->mnemonic, insn->op_str, int21h[r_ah]);
free(opcodes);

if (insn->id == X86_INS_RET)
goto end;
if (list_cmp_addr(jump, addr))
printf("\nlabel_0x%lx\n", addr);

if (insn->id == X86_INS_RET)
goto end;
}
else {
printf("0x%06" PRIx64 ":\t %-20s\t%s %s\n", insn->address, opcodes, insn->mnemonic, insn->op_str);
free(opcodes);

if (list_cmp_addr(jump, addr))
printf("\nlabel_0x%lx\n", addr);

if (insn->id == X86_INS_RET)
goto end;
}
}
cs_free(insn, 1);
}
Expand All @@ -279,6 +469,7 @@ void rt_disasm(uint64_t entry, uint64_t addr, size_t size, uint8_t *buffer, list
cs_close(&handle);
}


void ls_disasm(uint64_t addr, size_t size, uint8_t *buffer)
{
csh handle = 0;
Expand Down
1 change: 1 addition & 0 deletions core.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef struct {

typedef struct node {
uint64_t value;
bool visited;
struct node *next;
} list;

Expand Down
7 changes: 4 additions & 3 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ int main(int argc, char *argv[])
list *labl_addr = search_jump(get_entry(mz_hdr), get_exe_size(mz_hdr), buffer);

while (proc_addr) {
rt_disasm(get_entry(mz_hdr), proc_addr->value, get_exe_size(mz_hdr), buffer, proc_addr,
labl_addr);
if (!proc_addr->visited)
rt_disasm(get_entry(mz_hdr), proc_addr->value, get_exe_size(mz_hdr), buffer, proc_addr, labl_addr);
proc_addr = proc_addr->next;
}

Expand All @@ -102,7 +102,8 @@ int main(int argc, char *argv[])
list *labl_addr = search_jump(0, size, buffer);

while (proc_addr) {
rt_disasm(0, proc_addr->value, size, buffer, proc_addr, labl_addr);
if (!proc_addr->visited)
rt_disasm(0, proc_addr->value, size, buffer, proc_addr, labl_addr);
proc_addr = proc_addr->next;
}

Expand Down

0 comments on commit b4a0026

Please sign in to comment.