Location>code7788 >text

Reverse flower commands and anti-obfuscation

Popularity:247 ℃/2024-12-10 20:54:07

Flower Directive and Anti-Confusion

1. Flower instruction

  The flower instruction is a basic method of anti-debugging. Its presence interferes with the static analysis of the player, but does not affect the operation of the program. It is essentially a string of garbage instructions that has nothing to do with the function of the program itself and does not affect the logic of the program itself. In software protection, the flower instruction is used as a means to increase the difficulty of static analysis. ida does not recognize the flower instruction properly, resulting in the destruction of viewable and analyzable code, so we need to analyze it ourselves. Flower instructions are mainly divided into two categories: executable flower instructions and non-executable flower instructions.

  • Executable flower instructions: flower instructions are executed while the program is running normally, but do not affect the normal operation of the program.
  • Non-executable flower instructions: flower instructions are not executed when the program is running normally.

Commonly obfuscated bytecode:

machine code assembly language
9A CALL immed32
E8 CALL immed16
E9 JMP immed16
EB JMP immed8

2. Common flower instruction analysis

(1) Single byte

#include <>
int main()
{
    __asm {
        jz start; //jz and jnz at the same time, resulting in an eternal jump.
        jnz start;
        _emit 0xE8; //this is where the flower instruction CALL + address was intentionally inserted
    }
start.
    printf("ok!");
    return 0; }
}





Example: [NSSRound#3 Team]jump_by_jump

The main function won't compile. Look down and see the flower instruction.

To remove the flower command, press the D shortcut. Hard-code the call first, E8.

Put the cursor on db 0E8 again, change E8 to nop(90), press C again and hit yes to fix the hardcoding to code.

Then, repair downward one by one, placing the cursor over the column and pressing C until there are no more columns in color.

Place the cursor at the beginning of the function and press the P key to create a function and tab to pseudo-code.



(2) Eternal Jump

int main()
{
    __asm {
    xor eax, eax; // eax ^ eax = 0
    jz s; // must set up a jump, will definitely jump
    _emit 0x11; // fill garbage instruction byte type
    _emit 0x22; // fill garbage instruction byte type
    _emit 0x33; // fill garbage instruction byte type
    s.
    }
printf("test \n");
}

(3) Changing the ESP

int main()
{
    __asm {
        xor eax, eax.
        jz s.
        add esp, 0x11; // IDA will recognize this instruction as an operation on the function stack, resulting in a failure to identify the function
    s.
    }
    printf("test \n"); }
}

(4) jmp jumps to insert invalid garbage instructions

#define _CRT_SECURE_NO_WARNINGS
#include <>
int main()
{
    _asm {
    
        jmp $+5
        _emit 0x71
        _emit 2
        _emit 0xE9
        _emit 0xED
   }
 lable:
    printf("ok2");

    return 0;
}

(5) Nested Eternal Jump

#define _CRT_SECURE_NO_WARNINGS
#include <>
int main()
{
    _asm {
        jz Label3;
        jnz Label3;
        _emit 0xE8;
    }
Label2:
    _asm {
        jz Label4;
        jnz Label4;
        _emit 0xE8;
    }


Label3:
    _asm {
        jz Label1;
        jnz Label1;
        _emit 0xE9;
    }
Label1:
    _asm {
        jz Label2;
        jnz Label2;
        _emit 0xE9;
    }
Label4:
    printf("ok2");

    return 0;
}





3. Anti-Confusion

Method 1: Manual recovery

Applicable conditions: little confusion and single type
  In order to unlock the topic as quickly as possible, we generally choose to remove the obfuscation manually first to get the flag quickly
Here you need to master the basic IDA shortcuts: U, C, P

  1. U: In IDA Pro, press "U" to redefine assembly to bytecode format.
  2. C: Press "C" in IDA Pro to convert bytecode to assembly form.
  3. P: In IDA Pro, press "P" to convert assembly language to high-level language function view.

Method 2: IDA-Python Script Recovery

Applicable conditions: confusing large quantities, basically unremovable by hand
  Need to get the obfuscated bytecode composition and utilize scripts to remove a lot of the obfuscation.

Example: [GFCTF 2021] wordy

A large number of flower commands with machine code EBFF appear, which would be costly to nop manually, so here's the idapython

import idc
import ida_bytes

start_add=0x1144
end_add=0x3100
for address in range(start_add, end_add):
  new_byte = ida_bytes.get_byte(address)
  next = ida_bytes.get_byte(address + 1)
  nnext = ida_bytes.get_byte(address + 2)
  if new_byte == 0xeb and next == 0xff and nnext == 0xc0:  
    ida_bytes.patch_byte(address, 0x90)

  First the loop iterates over the data from the0x1144 until (a time)0x3100 at the address of the current byte. At each address, check whether the current byte is the0xebIf the next byte is0xffIf the next byte is0xc0. If the match is to0xeb 0xff 0xc0 This byte sequence then takes the byte at the current address0xeb modify to0x900x90 In assembly language, this is the NOP instruction, which means "no operation", i.e., this instruction has no effect on program execution.