flat assembler
Message board for the users of flat assembler.

Index > Main > [opcode] How to disable next instruction instead of Jxx?

Author
Thread Post new topic Reply to topic
wht36



Joined: 18 Sep 2005
Posts: 106
wht36 18 Sep 2005, 07:31
Sometimes I just want to skip the next instruction.
Is there a shorter way to do it instead of using jumps?

I know that to diable the next single-byte instruction one can use
an opcode such as 3Ch (cmp al,xx). For example:
Code:
checkhtm:   lodsb
            cmp    al,'<'
            jne    .not_a_tag                  ;if not html tag, store the char
            db     3Ch                         ;else skip storing char
.not_a_tag: stosb
            cmp    esi,end_of_buffer
            jb     checkhtm
    


Now... Are there other opcodes that can disable an instruction with larger sizes?
Post 18 Sep 2005, 07:31
View user's profile Send private message Reply with quote
Matrix



Joined: 04 Sep 2004
Posts: 1166
Location: Overflow
Matrix 18 Sep 2005, 07:49
if im right:

i did not tesz it yet,

Code:

checkhtm:   lodsb
            cmp    al,'<'
            jne    .not_a_tag                  ;if not html tag, store the char
            db $66 ; else skip next 2 bytes ; line x
            mov bx,$00 ; else skip next 2 bytes ; line y
.not_a_tag: stosd
            cmp    esi,end_of_buffer
            jb     checkhtm 
    

read again carefully, line x and line y are the prefix of stosd
should be compiled as : mov ebx,"stosd" $0000

alternatively on pentium class processors you can use cmovxx for conditional processing.


Last edited by Matrix on 18 Sep 2005, 11:04; edited 1 time in total
Post 18 Sep 2005, 07:49
View user's profile Send private message Visit poster's website Reply with quote
wht36



Joined: 18 Sep 2005
Posts: 106
wht36 18 Sep 2005, 10:02
Tried db $66 just now, doesn't work.
ollydbg displays $66 as superfluous data size
and still executes the next instruction.

cmovxx is a good idea, but doesn't allow me store single bytes, and there are times when I want to do something like:

Code:
entity_translations:
.copyrite:      mov     ax,'(c'
                stosw
                mov     al,')'
                jmp     .sto
.amp:           mov     al,'&'
                jmp     .sto
.gt:            mov     al,'>'
                jmp     .sto
.lt:            mov     al,'<'
                jmp     .sto
.nbsp:          mov     al,' '
.sto            stosb
                ...other stuff
    

and all that jmp are becoming an eyesore and I can't do something like cmovz al,'<'
Post 18 Sep 2005, 10:02
View user's profile Send private message Reply with quote
Matrix



Joined: 04 Sep 2004
Posts: 1166
Location: Overflow
Matrix 19 Sep 2005, 12:29
if you write:
Code:
checkhtm:   lodsb
            cmp    al,'<'
            jne    .not_a_tag                  ;if not html tag, store the char
            db $66,$b8 ; mov ebx, then 4 bytes data
.not_a_tag: stosd ; 2 bytes in 16 bit mode
                 stosd ; 2 bytes in 16 bit mode
            cmp    esi,end_of_buffer
            jb     checkhtm  
    
Post 19 Sep 2005, 12:29
View user's profile Send private message Visit poster's website Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend 19 Sep 2005, 19:49
You can use 0F2h (repnz) or 0F3h (rep/repz) but only if the next instruction is not in: lods, stos, cmps, ins, outs, scas

EDIT: Sorry, I misunderstood your question. Correct solutions would be: (1-byte instruction) 0A8h, (2-byte instruction) 066h, (3-byte instruction) 0A9h, 00h, (4-byte instruction) 0A9h
Code:
;       -----------------------------------------
        cmp     eax, TRUE
        jz      @F
        db      0A8h
    @@:
        push    eax                     ; 1 byte
;       -----------------------------------------
        cmp     eax, TRUE
        jz      @F
        db      066h, 0A9h
    @@:
        push    TRUE                    ; 2 bytes
;       -----------------------------------------
        cmp     eax, TRUE
        jz      @F
        db      0A9h, 000h
    @@:
        lea     eax, [eax+ecx]          ; 3 bytes
;       -----------------------------------------
        cmp     eax, TRUE
        jz      @F
        db      0A9h
    @@:
        lea     eax, [eax+ecx+1]        ; 4 bytes
;       -----------------------------------------    


EDIT2: You really intrigued me with your idea so I looked in my AMD documentations and found out another possible solution. But unfortunately it's the only two, there's no more (if we want to preserve all values, changing flags only). I created a special macro:
Code:
macro hide instr {
 virtual
  local __start, __size, __seed
  __start:
  instr
  load __seed byte from __start
  __size = $-__start
 end virtual
 if __size = 1
  if ((%t+__seed) mod 2) = 0
   db 0A8h
  else
   db 03Ch
  end if
 else if __size = 2
  if %t*__seed mod 1 = 0
   db 066h, 0A9h
  else
   db 066h, 03Dh
  end if
 else if __size = 3
  if %t*_seed mod 1 eq 0
   db 0A9h, 000h
  else
   db 03Dh, 000h
  end if
 else if __size = 4
  if %t*__seed mod 1 = 0
   db 0A9h
  else
   db 03Dh
  end if
 else
  display 'Instruction not hidden', 13, 10
 end if
 label @@
 instr }    

Usage:
Code:
        jmp     @F
  hide <push    eax> ; this will be done
  hide <push    ecx> ; skip this
        jmp     @F
  hide <push    edx> ; this will be done
  hide <push    ebx> ; skip this    
Everytime you hide any opcode, macro generates @@ label that points directly to the opcode, so that it can be done with a jump to @F (or @B)

EDIT3: Macro selects randomly which 'skipping prefix to use' depending on current timestamp and first byte of opcode


EDIT4: Smile Sorry for so many edits, but this topic got me really involved and I enjoy it very much! Smile Here is my next macro, which is in fact a modification of the previous one. It also randomly adds a prefix 0F2h or 0F3h before skipped instruction to obfuscate it even more. But it can be shut off changing the value of OBFUSCATE constant:
Code:
OBFUSCATE       equ TRUE

macro hide instr {
 virtual
  local __start, __size, __seed
  __start:
  instr
  load __seed byte from __start
  __size = $-__start
 end virtual
 local __bool_prefix, __bool_main
 __bool_main = ((%t+__seed) mod 2)
 match =TRUE, OBFUSCATE \{
  __bool_prefix = (((2*__seed*__seed*%t)+(4*__seed*%t)+(8*%t)) mod 3)
  if __bool_prefix = 0
   db 0F2h
  else if __bool_prefix = 1
   db 0F3h
  end if \}
 if __size = 1
  if __bool_main = 0
   db 0A8h
  else
   db 03Ch
  end if
 else if __size = 2
  if __bool_main = 0
   db 066h, 0A9h
  else
   db 066h, 03Dh
  end if
 else if __size = 3
  if __bool_main = 0
   db 0A9h, 000h
  else
   db 03Dh, 000h
  end if
 else if __size = 4
  if __bool_main = 0
   db 0A9h
  else
   db 03Dh
  end if
 else
  display 'Instruction not hidden', 13, 10
 end if
 label @@
 instr }    

Here's what OllyDbg gave me:
Code:
00401000 > $ /EB 02         jmp     short bin2asci.00401004
00401002     |66            db      66                               ;  CHAR 'f'
00401003   . |3D 31D27402   cmp     eax,274D231
00401008   .  3D 008D0440   cmp     eax,40048D00
0040100D   .  3C 51         cmp     al,51
0040100F   .  EB 02         jmp     short bin2asci.00401013
00401011      F2            db      F2
00401012      A8            db      A8
00401013   >  50            push    eax
00401014   .  3C 55         cmp     al,55
00401016   .  F9            stc
00401017   .  72 02         jb      short bin2asci.0040101B
00401019      3D            db      3D                               ;  CHAR '='
0040101A      00            db      00
0040101B   .  8D0480        lea     eax,[eax+eax*4]
0040101E   .  5A            pop     edx                              ;  kernel32.7C816D4F
0040101F   .  F2:           prefix repne:
00401020   .  3D 0083C464   cmp     eax,64C48300
00401025   .  EB 02         jmp     short bin2asci.00401029
00401027      66            db      66                               ;  CHAR 'f'
00401028      3D            db      3D                               ;  CHAR '='
00401029   >  01D0          add     eax,edx                          ;  ntdll.KiFastSystemCallRet
0040102B   .  C3            ret    
And in fact this code does:
Code:
       lea     eax, [eax*2+eax]
        push    eax
        lea     eax, [eax*4+eax]
        pop     edx
        add     eax, edx
        ret    
Post 19 Sep 2005, 19:49
View user's profile Send private message Visit poster's website Reply with quote
wht36



Joined: 18 Sep 2005
Posts: 106
wht36 20 Sep 2005, 09:50
Wow! Thanks! This is a cool macro you wrote! I had intended to find something to prevent too many jumps, but I had not realized one can use this kind of trick to confuse the disassembler as well! Very cool indeed!
Post 20 Sep 2005, 09:50
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.