Shabak challenge — Baby RISC

Instructions defined in header file asm_instructions.h
Registers defined in asm_processor_state.h
Memory allocation in asm_processor_state.c
tatic int generate_admin_code(uint8_t * payload, size_t max_size, size_t * payload_size_out)
{
int ret = E_SUCCESS;
char flag_string[MAX_FLAG_SIZE] = { 0 };
FILE * payload_fp = NULL;
ret = read_flag(flag_string, sizeof(flag_string));
if (ret != E_SUCCESS)
{
printf("Failed to read flag.\n");
goto cleanup;
}
payload_fp = fmemopen(payload, max_size, "w");
if (payload_fp == NULL)
{
ret = E_FOPEN;
goto cleanup;
}
// Write admin shellcode to payload buffer
// (Because E_SUCCESS == 0, we just OR all the return values, to check for error when we finish).
ret = E_SUCCESS;
// Pad out with newlines
for (size_t i = 0; i < 8; ++i)
{
ret |= file_write_opcode(payload_fp, PRINTNL);
}
// If the user sets R0 so (R0 * 42) == 1 (impossible!), she deserves to read the flag
ret |= file_write_opcode_imm32(payload_fp, ADDI, ASM_REGISTER_R1, ASM_REGISTER_ZERO, 42);
ret |= file_write_opcode3(payload_fp, MUL, ASM_REGISTER_R2, ASM_REGISTER_R0, ASM_REGISTER_R1);
ret |= file_write_opcode_imm32(payload_fp, SUBI, ASM_REGISTER_R2, ASM_REGISTER_R2, 1);
ret |= file_write_opcode1(payload_fp, RETNZ, ASM_REGISTER_R2);
// Print each 4-bytes of the flag as 4-characters
// (We might print some trailing null-characters if the flag length is not divisible by 4)
int32_t * flag_start = (int32_t *)flag_string;
int32_t * flag_end = (int32_t *)((char *)flag_string + strlen(flag_string));
for (int32_t * p = flag_start; p <= flag_end; ++p)
{
int32_t dword = *p;
ret |= file_write_opcode_imm32(payload_fp, ADDI, ASM_REGISTER_R1, ASM_REGISTER_ZERO, dword);
for (size_t j = 0; j < 4; j++)
{
ret |= file_write_opcode1(payload_fp, PRINTC, ASM_REGISTER_R1);
ret |= file_write_opcode_imm32(payload_fp, ROR, ASM_REGISTER_R1, ASM_REGISTER_R1, 8);
}
}
ret |= file_write_opcode(payload_fp, PRINTNL);
ret |= file_write_opcode(payload_fp, RET);
// Check if some error (other than E_SUCCESS) was recieved during the admin code generation
if (ret != E_SUCCESS)
{
ret = E_ADMIN_CODE_ERR;
goto cleanup;
}
// Success
long offset = ftell(payload_fp);
if (offset == -1)
{
ret = E_FTELL;
goto cleanup;
}
*payload_size_out = (size_t)offset;
cleanup:
if (payload_fp != NULL)
{
fclose(payload_fp);
}
return ret;
}
ADDI R1, ZERO, 42
MUL R2, R0, R1
SUBI R2, R2, 1
RETNZ R2
Writing to zero register returns an error
Code snippet in definition of push instruction

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store