Shabak challenge — Baby RISC

  • PRINTC to print the lower byte of a register as a character.
  • PRINTDD and PRINTDX to print the value of a register in decimal or hexadecimal formats, respectively.
  • PRINTNL to print a newline.
  • PUSH and POP.
  • RET, to terminate execution unconditionally.
  • RETNZ, to terminate execution if the given register is not zero.
  • RETZ, to terminate execution if the given register is zero.
  • ADD and ADDI
  • AND and ANDI
  • DIV and DIVI
  • and so on..
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)
goto cleanup;
// Success
long offset = ftell(payload_fp);
if (offset == -1)
ret = E_FTELL;
goto cleanup;
*payload_size_out = (size_t)offset;
if (payload_fp != NULL)
return ret;
MUL R2, R0, R1
SUBI R2, R2, 1
Writing to zero register returns an error
Code snippet in definition of push instruction




Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Browser Extensions that Everyone should have

My journey with development environments

Running SQL in a Jupyter Notebook

Managing complex tenant-environment user configurations

Create a Windows 10 Bootable USB Drive on Mac | 2021 Edition

create Windows 10 bootable usb on mac

How to Build your MVP Using the Facebook Groups API & Deploy as a Browser Extension

Big Objects 🏠 the Big Data solution by Salesforce ☁️


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
Anarta Poashan

Anarta Poashan


More from Medium

Chris Studer’s “Legends” Playlist


Luno E-Wallet : A Review

Why Avada Was Top Selling WordPress Theme in 2021