add: writing to arrays, hex in arrays fix: arguments parsing, show_error on windows

This commit is contained in:
2024-08-19 13:05:48 +02:00
parent a6e8d0d0f0
commit 5df51d811b
11 changed files with 121 additions and 29 deletions

34
examples/shellcode.pasm Normal file
View File

@@ -0,0 +1,34 @@
; Program that demonstrate the execution of a shellcode using pasm (using a Win32 calc.exe shellcode)
set arr 0x31, 0xc9, 0xf7, 0xe1, 0x64, 0x8b, 0x41, 0x30, 0x8b, 0x40, 0x0c, 0x8b, 0x70, 0x14, 0xad, 0x96, 0xad, 0x8b, 0x58, 0x10, 0x8b, 0x53, 0x3c, 0x01, 0xda, 0x8b, 0x52, 0x78, 0x01, 0xda, 0x8b, 0x72, 0x20, 0x01, 0xde, 0x31, 0xc9, 0x41, 0xad, 0x01, 0xd8, 0x81, 0x38, 0x47, 0x65, 0x74, 0x50, 0x75, 0xf4, 0x81, 0x78, 0x0a, 0x72, 0x65, 0x73, 0x73, 0x75, 0xeb, 0x8b, 0x72, 0x24, 0x01, 0xde, 0x66, 0x8b, 0x0c, 0x4e, 0x49, 0x8b, 0x72, 0x1c, 0x01, 0xde, 0x8b, 0x14, 0x8e, 0x01, 0xda, 0x89, 0xd5, 0x31, 0xc9, 0x68, 0x73, 0x41, 0x61, 0x61, 0x66, 0x81, 0x6c, 0x24, 0x02, 0x61, 0x61, 0x68, 0x6f, 0x63, 0x65, 0x73, 0x68, 0x74, 0x65, 0x50, 0x72, 0x68, 0x43, 0x72, 0x65, 0x61, 0x54, 0x53, 0xff, 0xd2, 0x31, 0xc9, 0xb1, 0xff, 0x31, 0xff, 0x57, 0xe2, 0xfd, 0x68, 0x63, 0x61, 0x6c, 0x63, 0x89, 0xe1, 0x51, 0x51, 0x31, 0xd2, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x51, 0x52, 0xff, 0xd0, 0x83, 0xc4, 0x10, 0x68, 0x65, 0x73, 0x73, 0x61, 0x66, 0x83, 0x6c, 0x24, 0x03, 0x61, 0x68, 0x50, 0x72, 0x6f, 0x63, 0x68, 0x45, 0x78, 0x69, 0x74, 0x54, 0x53, 0xff, 0xd5, 0x31, 0xc9, 0x51, 0xff, 0xd0
main:
push 64 ; flprotect (PAGE_EXECUTE_READWRITE)
push 12288 ; alloctype (MEM_COMMIT | MEM_RESERVE)
push 176 ; size
push 0 ; address
call VirtualAlloc
mov a4, eax ; copy of address
mov a1, eax ; address
mov a3, arr
mov a2, 0 ; count
memcpy:
cmp a2, 176
jne 1
jmp 6 ; jmp out of memcpy
mov *a1, *a3
add a1, 1
add a3, 8
add a2, 1
jmp memcpy
push a4
call CallRawAddress
memcpy_end:
push 32768 ; free type (MEM_RELEASE)
push 0 ; size (all)
push a4 ; address
call VirtualFree
end

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>../examples/array.pasm</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>../examples/shellcode.pasm</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -9,7 +9,7 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>../examples/array.pasm</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>../examples/ptr.pasm</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View File

@@ -43,3 +43,34 @@ void api_getasynckeystate() {
state->registers->eax = 1;
#endif
}
void api_virtualalloc() {
#ifdef _WIN32
long long address = state->STACK[state->STACK_IDX--];
long long size = state->STACK[state->STACK_IDX--];
long long alloctype = state->STACK[state->STACK_IDX--];
long long flprotect = state->STACK[state->STACK_IDX--];
state->registers->eax = (long long)VirtualAlloc((LPVOID)address, (SIZE_T)size, (DWORD)alloctype, (DWORD)flprotect);
#else
state->STACK_IDX -= 4;
state->registers->eax = 1;
#endif
}
void api_virtualfree() {
#ifdef _WIN32
long long address = state->STACK[state->STACK_IDX--];
long long size = state->STACK[state->STACK_IDX--];
long long freetype = state->STACK[state->STACK_IDX--];
state->registers->eax = VirtualFree((LPVOID)address, (SIZE_T)size, (DWORD)freetype);
#else
state->STACK_IDX -= 3;
state->registers->eax = 1;
#endif
}
void api_callrawaddr() {
long long address = state->STACK[state->STACK_IDX--];
((void (*)())address)();
}

View File

@@ -3,10 +3,16 @@
void api_put();
void api_getasynckeystate();
void api_virtualalloc();
void api_virtualfree();
void api_callrawaddr();
static const command_t api_map[] = {
{.command = "put", .fptr = api_put},
{.command = "GetAsyncKeyState", .fptr = api_getasynckeystate},
{.command = "VirtualAlloc", .fptr = api_virtualalloc},
{.command = "VirtualFree", .fptr = api_virtualfree},
{.command = "CallRawAddress", .fptr = api_callrawaddr},
{.command = NULL, .fptr = NULL}
};

View File

@@ -163,7 +163,7 @@ void debug_input(char *line) {
printf("%s is not a valid label or line number in this context", &in[2]);
break;
case 'e':
state->should_exit = 1;
state->should_exit = 0;
return;
case 'h':
default:

View File

@@ -4,7 +4,7 @@
#include "interpreter_states.h"
#define MAX_LINE 1024
#define MAX_LINE 2048
#ifdef _WIN32
extern int dprintf(int stream, const char *format, ...);

View File

@@ -45,6 +45,8 @@ bool check_args(s_arguments *args, int num_in_first, int num_args) {
}
long long* get_reg(char* reg_char) {
int deref = reg_char[0] == '*';
if (reg_char[0] == '&' || reg_char[0] == '*')
++reg_char;
for (int i = 0; i < state->num_arrays; i++)
@@ -52,25 +54,25 @@ long long* get_reg(char* reg_char) {
return (long long *)&state->ARRAYS_VALUES[i];
switch (reg_char[1]) {
case '1' :
return &state->registers->a1;
return deref ? (long long*)state->registers->a1 : &state->registers->a1;
case '2' :
return &state->registers->a2;
return deref ? (long long*)state->registers->a2 : &state->registers->a2;
case '3' :
return &state->registers->a3;
return deref ? (long long*)state->registers->a3 : &state->registers->a3;
case '4' :
return &state->registers->a4;
return deref ? (long long*)state->registers->a4 : &state->registers->a4;
case '5' :
return &state->registers->a5;
return deref ? (long long*)state->registers->a5 : &state->registers->a5;
case '6' :
return &state->registers->a6;
return deref ? (long long*)state->registers->a6 : &state->registers->a6;
case '7' :
return &state->registers->a7;
return deref ? (long long*)state->registers->a7 : &state->registers->a7;
case '8' :
return &state->registers->a8;
return deref ? (long long*)state->registers->a8 : &state->registers->a8;
case '9' :
return &state->registers->a9;
return deref ? (long long*)state->registers->a9 : &state->registers->a9;
case 'a' : //eax
return &state->registers->eax;
return deref ? (long long*)state->registers->eax : &state->registers->eax;
default :
return NULL; //should never happen
}
@@ -83,9 +85,6 @@ long long get_value(char* arg) {
if (arg[0] == '&') {
ret = (long long)get_reg(arg);
}
else if (arg[0] == '*') {
ret = *(long long *)(*get_reg(arg));
}
else {
ret = *get_reg(arg);
}
@@ -289,6 +288,7 @@ void push() {
}
}
else {
if (state->args->arg1[0] != '0')
value = (int)state->args->arg1[0];
}
}
@@ -327,5 +327,5 @@ void _xor() {
}
void end() {
state->should_exit = 1;
state->should_exit = 0; //could use EAX for return code but i don't think i care
}

View File

@@ -50,6 +50,7 @@ int init_state() {
state->STACK_IDX = -1;
state->last_stack_code = STACK_OK;
state->last_check_args_code = OK;
state->should_exit = -1;
return 0;
}
@@ -215,7 +216,12 @@ ARRAY_ERR add_array(char* line) {
while (ptr != NULL && j < array_size) {
if (ptr[0] == ' ')
++ptr;
if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') {
arr[j++] = strtol(ptr, NULL, 16);
}
else {
arr[j++] = atoi(ptr);
}
ptr = strtok(NULL, ",");
}
state->ARRAYS_VALUES[state->num_arrays++] = arr;
@@ -243,6 +249,19 @@ char *extract_arg(char *ptr, int a) {
return arg;
}
void sanitize_arguments() { //removes trailing spaces
if (state->args->arg1 == NULL)
return;
for (int i = 0; state->args->arg1[i] != '\0'; i++)
if (state->args->arg1[i] == ' ' || state->args->arg1[i] == '\t' || state->args->arg1[i] == '\n')
state->args->arg1[i] = '\0';
if (state->args->arg2 == NULL)
return;
for (int i = 0; state->args->arg2[i] != '\0'; i++)
if (state->args->arg2[i] == ' ' || state->args->arg2[i] == '\t' || state->args->arg2[i] == '\n')
state->args->arg2[i] = '\0';
}
int parse_arguments(char *line) {
strcpy(state->args->arg1, "");
strcpy(state->args->arg2, "");

View File

@@ -78,4 +78,5 @@ void set_exit_state(int exit_state);
int get_exit_state();
LABEL_ERR add_label(char *label, int line);
ARRAY_ERR add_array(char *line);
void sanitize_arguments();
int parse_arguments(char *args);

View File

@@ -36,7 +36,7 @@ int dprintf(int stream, const char * format, ...) {
void show_error(size_t line, char *line_) {
#ifdef _WIN32
int wrote = dprintf(fstream, "%llu| ", line + 1);
int wrote = dprintf(fstream, "%ld| ", line + 1);
#else
int wrote = dprintf(fstream, "%ld| ", line + 1);
#endif
@@ -97,7 +97,7 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
}
int found_main = 0;
for (state->curr_line = 0; state->curr_line < (int)lines && get_exit_state() == 0 ; ++state->curr_line) {
for (state->curr_line = 0; state->curr_line < (int)lines && get_exit_state() == -1 ; ++state->curr_line) {
if (pasm_debug_mode && found_main)
debug_input(file[state->curr_line]);
#ifdef _WIN32
@@ -137,6 +137,7 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
continue;
}
parse_arguments(file[state->curr_line]);
sanitize_arguments();
if (found_main)
com->fptr();
if (check_errors(file[state->curr_line])) {