add: writing to arrays, hex in arrays fix: arguments parsing, show_error on windows
This commit is contained in:
34
examples/shellcode.pasm
Normal file
34
examples/shellcode.pasm
Normal 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
|
||||
@@ -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'">
|
||||
|
||||
31
src/api.c
31
src/api.c
@@ -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)();
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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, ...);
|
||||
|
||||
@@ -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,11 +85,8 @@ 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);
|
||||
else {
|
||||
ret = *get_reg(arg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -289,7 +288,8 @@ void push() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = (int)state->args->arg1[0];
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
arr[j++] = atoi(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, "");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -86,7 +86,7 @@ int check_errors(char *line) {
|
||||
/* _fstream: file descriptor for the output (can be a socket), default: stderr */
|
||||
/* return value: nonzero if an error occurred */
|
||||
int pasm_run_script(const char *filename, char **file, size_t lines, int _fstream) {
|
||||
fstream = _fstream;
|
||||
fstream = _fstream;
|
||||
|
||||
if (filename && read_script(filename, &file, &lines) == 1)
|
||||
return 1;
|
||||
@@ -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])) {
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 3 || (argc == 2 && strcmp(argv[1], "-h") == 0) || (argc != 2 && argc != 3)) {
|
||||
fprintf(stderr, "usage : %s filename [-d/--debug]\n", argv[0]);
|
||||
return 1;
|
||||
fprintf(stderr, "usage : %s filename [-d/--debug]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (argc == 3 && (strcmp(argv[2], "-d") == 0 || strcmp(argv[2], "--debug") == 0)) {
|
||||
pasm_debug_mode = 1;
|
||||
printf("pasm: debug mode activated.\n");
|
||||
pasm_debug_mode = 1;
|
||||
printf("pasm: debug mode activated.\n");
|
||||
}
|
||||
return pasm_run_script(argv[1], 0, 0, 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user