add ret, call, stack
v1 let's go !
This commit is contained in:
10
README.md
10
README.md
@@ -9,11 +9,11 @@ PASM is meant for being used in C2 agents as its interpreter is small.
|
||||
PASM is not a language that you daily use, it is not meant for big projects but rather for scripting using existing API (here the Windows API's but it can get extended).
|
||||
|
||||
# Current state
|
||||
At the moment i'm trying to get everything working before refactoring (there are bad practices and redundant code) and getting rid of the CRT, here is what is left to do :
|
||||
- make control flow work (ret is gonna be a pain) (i need to fix the char_read counter, strlen doing its things ig)
|
||||
- add the API
|
||||
- think of a more clever way of going through the labels and later the API (currently done in get_instruction.c and instructions.c)
|
||||
- make the stack work
|
||||
PASM is in a working state, the [keylogger example](#code-examples) works like a charm.
|
||||
|
||||
TODO :
|
||||
- code refactor (still bad practices)
|
||||
- get rid of the CRT (so we can get a smaller PE)
|
||||
- write the docs
|
||||
|
||||
# Usage
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# keylogger
|
||||
This is a POC, i don't even know if it works as the interpreter and scripts are in very early stages
|
||||
Will output the pressed key. Works for keys from A-Z and 0-9.
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
; note about returns : you can directly call ret from a je/jne/ja/jna/jb/jnb with "jb return".
|
||||
; so return cannot be used as a label.
|
||||
check:
|
||||
cmp a1, 58
|
||||
cmp a1, 57
|
||||
jb return ; if <
|
||||
|
||||
cmp a1, 64
|
||||
cmp a1, 63
|
||||
ja return ; if >
|
||||
|
||||
mov eax, 1
|
||||
@@ -48,12 +48,11 @@ add a1, 1 ; i++
|
||||
|
||||
push a1 ; arg 1 (vKey)
|
||||
call GetAsyncKeyState
|
||||
and eax, 32768 ; 0x8000 but i haven't implemented hex yet
|
||||
and eax, 1
|
||||
cmp eax, 0
|
||||
je numbers ; if GetAsyncKeyState was false, jump to numbers
|
||||
|
||||
mov a2, a1 ; necessary ?
|
||||
push "%c" ; push format
|
||||
push a2 ; push char
|
||||
call printf
|
||||
call put
|
||||
jmp numbers
|
||||
13
src/api.c
13
src/api.c
@@ -1 +1,12 @@
|
||||
#include "api.h"
|
||||
#include "api.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
void api_put() {
|
||||
printf("%c\n", stack[top--]);
|
||||
}
|
||||
|
||||
void api_getasynckeystate() {
|
||||
eax = GetAsyncKeyState(stack[top--]);
|
||||
}
|
||||
@@ -1,3 +1,12 @@
|
||||
#pragma once
|
||||
#include "instructions.h"
|
||||
|
||||
void api_put();
|
||||
void api_getasynckeystate();
|
||||
|
||||
static const command_t api_map[] = {
|
||||
{.command = "put", .fptr = api_put},
|
||||
{.command = "GetAsyncKeyState", .fptr = api_getasynckeystate},
|
||||
|
||||
{.command = NULL, .fptr = NULL}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "instructions.h"
|
||||
#include "main.h"
|
||||
#include "api.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -64,13 +65,13 @@ int get_value(char* arg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const command_t *find_command(char *your_var)
|
||||
const command_t *find_command(char *your_var, const command_t* func_map)
|
||||
{
|
||||
if (your_var == NULL)
|
||||
return NULL;
|
||||
for (int index = 0; command_map[index].fptr != NULL; index += 1) {
|
||||
if (strcmp(your_var, command_map[index].command) == 0) {
|
||||
return &command_map[index];
|
||||
for (int index = 0; func_map[index].fptr != NULL; index += 1) {
|
||||
if (strcmp(your_var, func_map[index].command) == 0) {
|
||||
return &func_map[index];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -92,11 +93,30 @@ void cmp() {
|
||||
return;
|
||||
}
|
||||
|
||||
int line_should_ret = -1;
|
||||
void ret() {
|
||||
if (line_should_ret == -1) {
|
||||
exit_code = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fseek(fptr, line_should_ret, SEEK_SET);
|
||||
}
|
||||
|
||||
void jmp() {
|
||||
if (strcmp(args->arg1, "return") == 0) {
|
||||
ret();
|
||||
return;
|
||||
}
|
||||
|
||||
eax = 0;
|
||||
for (int i = 0; i < MAX_LABEL; i++) {
|
||||
if (labels[i] == NULL) break;
|
||||
if (strcmp(args->arg1, labels[i]) == 0) {
|
||||
line_should_ret = (int)char_read;
|
||||
fseek(fptr, labels_lines[i], SEEK_SET);
|
||||
(int)char_read = labels_lines[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -153,20 +173,37 @@ void mov() {
|
||||
*get_reg(args->arg1) = get_value(args->arg2);
|
||||
}
|
||||
|
||||
void ret() {
|
||||
|
||||
}
|
||||
|
||||
void call() {
|
||||
|
||||
const command_t* com = find_command(args->arg1, api_map);
|
||||
if (com != NULL) {
|
||||
com->fptr();
|
||||
}
|
||||
else {
|
||||
last_jmp_code = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void push() {
|
||||
if (!((is_num(args->arg1) || (is_reg(args->arg1))))) {
|
||||
last_check_args_code = ARG1_WRONG;
|
||||
return;
|
||||
}
|
||||
|
||||
if (top == STACK_SIZE) { //stack overflow
|
||||
last_stack_code = OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
stack[++top] = get_value(args->arg1);
|
||||
}
|
||||
|
||||
void pop() {
|
||||
if (top == -1) { //stack underflow
|
||||
last_stack_code = UNDERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
--top;
|
||||
}
|
||||
|
||||
void and() {
|
||||
|
||||
@@ -18,13 +18,20 @@ typedef enum check_args_codes {
|
||||
} check_args_codes ;
|
||||
extern check_args_codes last_check_args_code;
|
||||
|
||||
typedef enum stack_codes {
|
||||
OVERFLOW,
|
||||
UNDERFLOW,
|
||||
STACK_OK
|
||||
} stack_codes;
|
||||
extern stack_codes last_stack_code;
|
||||
|
||||
//pasted from https://github.com/Sakutaroo/Templates/blob/main/C/FunctionPointer/function_pointer.h
|
||||
typedef struct command_s {
|
||||
char *command;
|
||||
void (*fptr)();
|
||||
} command_t;
|
||||
|
||||
const command_t *find_command(char *your_var);
|
||||
const command_t* find_command(char* your_var, const command_t* func_map);
|
||||
|
||||
bool check_args(int num_in_first);
|
||||
|
||||
|
||||
26
src/main.c
26
src/main.c
@@ -10,15 +10,19 @@ void show_help() {
|
||||
}
|
||||
|
||||
arguments* args = NULL;
|
||||
int stack[9] = {0*9};
|
||||
int stack[STACK_SIZE] = {0*STACK_SIZE};
|
||||
int top = -1;
|
||||
int a1, a2, a3, a4, a5, a6, a7, a8, a9, eax = 0;
|
||||
char* labels[256] = {0*256};
|
||||
int labels_lines[256] = {0*256};
|
||||
int num_labels = 0;
|
||||
FILE* fptr = NULL;
|
||||
last_jmp_code = 0;
|
||||
stack_codes last_stack_code = STACK_OK;
|
||||
cmp_return_codes last_cmp_code = CMP_EQUAL;
|
||||
last_check_args_code = OK; //init error code
|
||||
size_t char_read = 0;
|
||||
int exit_code = 0;
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
printf("Bad arguments.\n");
|
||||
@@ -41,10 +45,9 @@ int main(int argc, char** argv) {
|
||||
args = (arguments*)calloc(1, sizeof(arguments));
|
||||
|
||||
char line[256];
|
||||
int line_number = 1;
|
||||
size_t char_read = 0;
|
||||
const command_t* com = NULL;
|
||||
int main_hit = 0;
|
||||
int line_number = 1;
|
||||
while (fgets(line, sizeof(line), fptr)) {
|
||||
char_read += strlen(line) + 1;
|
||||
|
||||
@@ -74,7 +77,7 @@ int main(int argc, char** argv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
com = find_command(ins);
|
||||
com = find_command(ins, command_map);
|
||||
if (com != NULL) {
|
||||
get_args(line, args_pos);
|
||||
}
|
||||
@@ -132,6 +135,21 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (last_stack_code != STACK_OK) {
|
||||
printf("%s ^\n |\nstack %s on line %d", line, last_stack_code == OVERFLOW ? "overflow" : "underflow", line_number);
|
||||
free(args->arg1);
|
||||
free(args->arg2);
|
||||
free(args);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (exit_code) {
|
||||
free(args->arg1);
|
||||
free(args->arg2);
|
||||
free(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
++line_number;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#include "instructions.h"
|
||||
#include <stdio.h>
|
||||
#define MAX_LABEL 256
|
||||
#define STACK_SIZE 9
|
||||
|
||||
extern int stack[9];
|
||||
extern int top;
|
||||
extern int stack[STACK_SIZE];
|
||||
extern int a1, a2, a3, a4, a5, a6, a7, a8, a9, eax; //registers
|
||||
extern char* labels[MAX_LABEL]; //max 256 labels
|
||||
extern int labels_lines[MAX_LABEL]; //line numbers for the labels
|
||||
@@ -11,6 +13,8 @@ extern int num_labels; //number of labels already in use
|
||||
extern cmp_return_codes last_cmp_code;
|
||||
extern int last_jmp_code; //easier when global
|
||||
extern FILE* fptr; //file pointer
|
||||
extern int exit_code;
|
||||
extern size_t char_read;
|
||||
|
||||
typedef struct arguments{
|
||||
char* arg1;
|
||||
|
||||
@@ -48,7 +48,7 @@ void get_args(char* line, int args_start_pos) {
|
||||
|
||||
int write_to_first = 1; //ugly hack but whatever
|
||||
int j = 0;
|
||||
for (int i = args_start_pos; i < (int)strlen(line); i++) {
|
||||
for (int i = args_start_pos; i < (int)strlen(line)+1; i++) {
|
||||
if (line[i] == '\n' || line[i] == '\0' || line[i] == ';') {
|
||||
second_arg[j] = '\0';
|
||||
args->arg2 = (char*)calloc(1, strlen(second_arg) + 1);
|
||||
|
||||
Reference in New Issue
Block a user