diff --git a/INSTRUCTION_SET.md b/INSTRUCTION_SET.md new file mode 100644 index 0000000..9f9e8ed --- /dev/null +++ b/INSTRUCTION_SET.md @@ -0,0 +1,333 @@ +# Architecture + +Pasticciotto uses the Harvard Architecture meaning its code is separated from its data and also from its stack. This allowed me to materialize my idea for the **PoliCTF** challenge: I could run the code the partecipants assembled without any hassle! +![Structure] + +There are 8 general purpose registers (`R0` to `S3`) with `S0 -> S3` being "scratch" ones. There is a `RP` register (Return Pointer) and obviously the `IP` (Instruction Pointer). + +# Opcode encryption + +The VM needs a decryption key to run: the opcodes are "encrypted" with the key by the assembler. The encryption algorithm is the `RC4` key scheduling shuffle. Once the values are shuffled, the `opcodes` are assigned according to their definition order. + +```python +key_ba = bytearray(key, 'utf-8') +# RC4 KSA! :-P +arr = [i for i in range(256)] +j = 0 +for i in range(len(arr)): + j = (j + arr[i] + key_ba[i % len(key)]) % len(arr) + arr[i], arr[j] = arr[j], arr[i] + +for i, o in enumerate(ops): + o.set_value(arr[i]) +``` + +# Instruction set +The instruction set I come out wants to be "RISC"-oriented but I have to admit that it is more "CISC"-oriented *(Confusing Instruction Set Computer)*. +Also, since I decided that every instruction had to be 4 chars long, some name adaptation may have encountered some quality issue... (yes, `POP`, I'm looking at you) + +**The syntax used is the Intel one!** + +There **three types** of instructions: +1. with 2 operands (*imm2reg*, *reg2imm*, *byt2reg*, *reg2reg*) +2. with 1 operand +3. with no operand at all (*single*) + +![Instruction] +## MOVI +``` +Full name: MOVe Immediate to register +Usage: MOVI R0, 0x00 +Effect: R0 contains the value 0x00 +``` +## MOVR +``` +Full name: MOVe Register to register +Usage: MOVR R1, R0 +Effect: R0 is copied into R1 +``` +## LODI +``` +Full name: LOaD Immediate offset @ data section to register +Usage: LODI R0, 0x0 +Effect: R0 contains data[0x0] +``` +## LODR +``` +Full name: LOaD offset in Register @ data section to register +Usage: LODR R1, R0 +Effect: R1 contains data[R1] +``` +## STRI +``` +Full name: SToRe @ immediate offset in data section from register +Usage: STRI 0x0, R0 +Effect: data[0x0] contains R0 +``` +## STRR +``` +Full name: SToRe @ offset of Register in data section from register +Usage: STRR R1, R0 +Effect: data[R1] contains R0 +``` +## ADDI +``` +Full name: ADD Immediate to register +Usage: ADDI R0, 0x1 +Effect: R0 is incremented by 0x1 +``` +## ADDR +``` +Full name: ADD Register to register +Usage: ADDR R1, R0 +Effect: R1 is incremented by R0 +``` +## SUBI +``` +Full name: SUBstract Immediate from register +Usage: SUBI R0, 0x1 +Effect: R0 is decremented by 0x1 +``` +## SUBR +``` +Full name: SUBstract Register from register +Usage: SUBR R1, R0 +Effect: R1 is decremented by R0 +``` +## ANDB +``` +Full name: +Usage: +Effect: +``` +## ANDW +``` +Full name: +Usage: +Effect: +``` +## ANDR +``` +Full name: +Usage: +Effect: +``` +## YORB +``` +Full name: +Usage: +Effect: +``` +## YORW +``` +Full name: +Usage: +Effect: +``` +## YORR +``` +Full name: +Usage: +Effect: +``` +## XORB +``` +Full name: +Usage: +Effect: +``` +## XORW +``` +Full name: +Usage: +Effect: +``` +## XORR +``` +Full name: +Usage: +Effect: +``` +## NOTR +``` +Full name: +Usage: +Effect: +``` +## MULI +``` +Full name: +Usage: +Effect: +``` +## MULR +``` +Full name: +Usage: +Effect: +``` +## DIVI +``` +Full name: +Usage: +Effect: +``` +## DIVR +``` +Full name: +Usage: +Effect: +``` +## SHLI +``` +Full name: +Usage: +Effect: +``` +## SHLR +``` +Full name: +Usage: +Effect: +``` +## SHRI +``` +Full name: +Usage: +Effect: +``` +## SHRR +``` +Full name: +Usage: +Effect: +``` +## PUSH +``` +Full name: +Usage: +Effect: +``` +## POOP +``` +Full name: +Usage: +Effect: +``` +## CMPB +``` +Full name: +Usage: +Effect: +``` +## CMPW +``` +Full name: +Usage: +Effect: +``` +## CMPR +``` +Full name: +Usage: +Effect: +``` +## JMPI +``` +Full name: JuMP to Immediate +Usage: JMPI 0x00 +Effect: Unconditional jump to 0x00 +``` +## JMPR +``` +Full name: JuMP to Register +Usage: JMPR R0 +Effect: Unconditional jump to R0 +``` +## JPAI +``` +Full name: JumP if Above to Immediate +Usage: JPAI 0x00 +Effect: Jumps to code[0x00] according to last comparison +``` +## JPAR +``` +Full name: JumP if Above to Register +Usage: JPAR R0 +Effect: Jumps to code[R0] according to last comparison +``` +## JPBI +``` +Full name: JumP if Below or equal to Immediate +Usage: JPBI 0x00 +Effect: Jumps to code[0x00] according to last comparison +``` +## JPBR +``` +Full name: JumP if Below or equal to Register +Usage: JPBR R0 +Effect: Jumps to code[R0] according to last comparison +``` +## JPEI +``` +Full name: JumP if Equal to Immediate +Usage: JPEI 0x00 +Effect: Jumps to code[0x00] according to last comparison +``` +## JPER +``` +Full name: JumP if Equal to Register +Usage: JPER R0 +Effect: Jumps to code[R0] according to last comparison +``` +## JPNI +``` +Full name: JumP if Not equal to Immediate +Usage: JPNI 0x00 +Effect: Jumps to code[0x00] according to last comparison +``` +## JPNR +``` +Full name: JumP if Not equal to Register +Usage: JPNR R0 +Effect: Jumps to code[R0] according to last comparison +``` +## CALL +``` +Full name: CALL function +Usage: CALL *function* +Effect: Saves the next instruction address into RP and jumps to the start of the function +``` +## RETN +``` +Full name: RETurN +Usage: RETN +Effect: Restores the RP into the IP and jumps to the IP +``` +## SHIT +``` +Full name: Well... +Usage: SHIT +Effect: Halts the execution +``` +## NOPE +``` +Full name: NOP(e) +Usage: NOPE +Effect: Does nothing for an instruction +``` +## GRMN +``` +Full name: GeRMaNo +Usage: GRMN +Effect: Sets every register (excluding IP and RP) to GG +``` +## DEBG +``` +Full name: DEBuG +Usage: DEBG +Effect: Prints the status of every register and the flags +``` + +[Instruction]: ./res/instruction.png +[Structure]: ./res/structure.png diff --git a/README.md b/README.md index 3aa8f82..13fbc11 100644 --- a/README.md +++ b/README.md @@ -1 +1,47 @@ -VM con ISA diversi e bytecode generati casualmente. \ No newline at end of file +![Pasticciotto] + +# What is this? +Pasticciotto is a virtual machine which can be used to obfuscate code. It was developed for the **PoliCTF 17** as a reversing challenge. + +I wanted to experiment with VM obfuscation since it was a topic that caught my attention while reversing challenges for various CTFs. So, I decided to write one **from scratch** in order to understand better how instruction set architectures are implemented! + +The design and the implementation behind Pasticciotto are not state-of-the-art but hey, it works! + +# What about the challenge? +I do not want to spoil the challenge for those that haven't completed it yet. Check out some write-up online! + +# Instruction set +Check out the file [INSTRUCTION_SET.MD](IS) to understand how the VM works and which operations it can do! Watch out for some spoilers if you haven't completed the challenge though! + +# Why "Pasticciotto"? +In Italian, "Pasticciotto" has two meanings! + +The first one is **"little mess"** which perfectly describes how I put up this project. The second one is a typical dessert from Southern Italy, Salento! It's filled with cream! Yum! + +# Contributions + +Any contribution is **very** welcome! Feel free to open issues and pull requests! + + +# License +``` +Copyright 2017 Giulio De Pasquale + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +``` +[Pasticciotto]: ./res/pasticciotto.png +[IS]: ./INSTRUCTION_SET.md \ No newline at end of file diff --git a/assembler/assembler.py b/assembler/assembler.py index 09892ba..4764dd5 100644 --- a/assembler/assembler.py +++ b/assembler/assembler.py @@ -55,7 +55,7 @@ class VMAssembler: self.data = data self.assembled_code = bytearray() self.functions = [] - self.decrypt_ops(key) + self.encrypt_ops(key) self.parse_functions() self.resolve_functions_offsets() self.resolve_symbols() @@ -252,7 +252,7 @@ class VMAssembler: self.assembled_code += opcode.uint8() return - def decrypt_ops(self, key): + def encrypt_ops(self, key): key_ba = bytearray(key, 'utf-8') olds = copy.deepcopy(ops) diff --git a/res/instruction.png b/res/instruction.png new file mode 100644 index 0000000..61e199e Binary files /dev/null and b/res/instruction.png differ diff --git a/res/pasticciotto.png b/res/pasticciotto.png new file mode 100644 index 0000000..7304dc2 Binary files /dev/null and b/res/pasticciotto.png differ diff --git a/res/structure.png b/res/structure.png new file mode 100644 index 0000000..5b88cb5 Binary files /dev/null and b/res/structure.png differ diff --git a/res/structure.svg b/res/structure.svg new file mode 100644 index 0000000..6abfdff --- /dev/null +++ b/res/structure.svg @@ -0,0 +1,2 @@ + +
Pasticciotto
 VM
[Not supported by viewer]
MOVI S0, 0x1
ADDI S0, 0xff
...
[Not supported by viewer]
CODE
CODE
"HELLO!"
<div>"HELLO!"</div>
DATA
DATA
0x0000
0x1234
0x5678
[Not supported by viewer]
STACK
STACK
R0
R0
R2
R2
R3
R3
R1
R1
S0
S0
S2
S2
S3
S3
S1
S1
RP
RP
IP
IP
16 bits: 0x0000 -> 0xFFFF
16 bits: 0x0000 -&gt; 0xFFFF
bit 0
bit 0
bit 15
bit 15
\ No newline at end of file