home *** CD-ROM | disk | FTP | other *** search
/ Cracking 2 / Cracking II..iso / Tools / ApiHooks 3.0 / REMEXEC.INC < prev    next >
Encoding:
Text File  |  2000-06-18  |  21.5 KB  |  605 lines

  1. ;-------------------------------------------------------------------------------
  2. ;Creates remote thread in the process specified by procID and which handle
  3. ;is in EBX register.
  4. ;Returns ApiHooks ErrorCodes.
  5.  
  6. RemoteExecNT       PROC  USES  ESI, procID, ExpTime, lpBlock, BlockSize, lpCodeEnd
  7.    LOCAL     ThreadStack: DWORD
  8.    LOCAL     tbi :THREAD_BASIC_INFORMATION
  9.    LOCAL     hThreadTIDField[MAX_HTIDTHREAD*2+1] :HANDLE
  10.  
  11. ;Suspend all threads in the target ---
  12.    AND       ThreadStack, 0
  13.    LEA       ESI, hThreadTIDField
  14. ;of course there's no need to find a suitable thread
  15. ;just suspend all threads
  16.    sWin32    FindThread,   THREAD_SUSPEND_RESUME OR THREAD_GET_CONTEXT OR \
  17.                            THREAD_SET_CONTEXT OR \ ; THREAD_SET_INFORMATION OR \
  18.                            THREAD_QUERY_INFORMATION,\
  19.                            FALSE,\
  20.                            procID,\
  21.                            ESI
  22.    TEST      EAX, EAX
  23.    PUSH      ErrorRemoteExec
  24.    JE        REFailed
  25. ;-------------------------------------
  26.  
  27.    PUSH      EDI
  28.    MOV       ESI, NTThreadExit
  29.    MOV       EDI, lpCodeEnd
  30.    MOVSD                  ;copy end sequence at CodeEnd
  31.    MOVSD
  32.    MOVSD
  33.    POP       EDI          ;write it to the process
  34.    iWin32    WriteProcessMemory, EBX, EDI, lpBlock, BlockSize, NULL
  35.    TEST      EAX, EAX
  36.    JE        REFailure    ;can't write
  37.  
  38. ;I'm not using CreateRemoteThread because it is too hilevel. It requires
  39. ;KERNEL32.dll to be present in the target. Moreover when are all csrss.exe's
  40. ;threads suspended, CRT never returns (hangs OS).
  41.  
  42.    PUSH      EAX          ;place for thread handle
  43.    MOV       EDX, ESP
  44.    sWin32    RtlCreateUserThread, EBX,  NULL, TRUE,\    ;TRUE == suspended
  45.                                   NULL, NULL, NULL,\
  46.                                   EDI,  NULL, EDX, NULL
  47.    TEST      EAX, EAX
  48.    POP       ESI          ;hThread
  49.    JL        REFailure    ;native api returned NTSTATUS -> check for signum bit if failed
  50.  
  51.   ;get remote thread's stack memory
  52.    LEA       ECX, tbi
  53.    sWin32    NtQueryInformationThread, ESI, ThreadBasicInformation, ECX, SIZEOF tbi, 0
  54.    TEST      EAX, EAX
  55.    JL        @F           ;native api returned NTSTATUS
  56.    MOV       EAX, tbi.TebBaseAddress
  57.    TEST      EAX, EAX
  58.    JE        @F
  59.    LEA       ECX, ThreadStack     ;read it here
  60.    ADD       EAX, TEB.ThreadStack
  61.    iWin32    ReadProcessMemory, EBX, EAX, ECX, 4, NULL
  62.   @@:
  63.    iWin32    ResumeThread, ESI         ;go on
  64.    iWin32    WaitForSingleObject, ESI, ExpTime
  65.    CMP       EAX, WAIT_TIMEOUT
  66.    JNE       @F
  67.    oMOV      [ESP], ErrorTimeOut
  68.    JMP       REFailureClose
  69.   @@:
  70.    LEA       ECX, tbi     ;do GetExitCodeThread:
  71.    sWin32    NtQueryInformationThread, ESI, ThreadBasicInformation, ECX, SIZEOF tbi, 0
  72.    oMOV      [ESP], tbi.ExitStatus
  73.   REFailureClose:
  74.    iWin32    CloseHandle, ESI
  75.  
  76.   REFailure:
  77. ;Desuspend and close all threads ---
  78.    LEA       ESI, hThreadTIDField
  79.    PUSH      ESI
  80.    sWin32    DeSuspend, ESI, -1
  81.    POP       ESI
  82.   REFailed:
  83.    LODSD
  84.    TEST      EAX, EAX
  85.    JE        ThreadsClosed
  86.    iWin32    CloseHandle, EAX
  87.    LODSD
  88.    JMP       REFailed
  89.   ThreadsClosed:
  90. ;-----------------------------------
  91.    CMP       DWORD PTR [ESP], ErrorTimeOut  ;if there was timeout let it be
  92.    JE        @F                             ;and don't free anything
  93.    MOV       ECX, ThreadStack
  94.    JECXZ     DontFree
  95.    sWin32    RemoteFreeNT, ECX     ;free remote thread stack in target
  96.   DontFree:
  97.   RemFree:
  98.    sWin32    RemoteFreeNT, EDI     ;free allocated memory in target
  99.    TEST      EAX, EAX
  100.    JNE       @F
  101.    CMP       DWORD PTR [ESP], ErrorSuccess  ;evaluate error code
  102.    JNE       @F
  103.    oMOV      [ESP], ErrorRemoteFree
  104.   @@:
  105.    POP       EAX
  106.    RET
  107. RemoteExecNT       ENDP
  108. ;-------------------------------------------------------------------------------
  109. ;structure shorter than CONTEXT for saving memory:
  110.    _CONTEXT STRUCT
  111.      ContextFlags  DWORD ?
  112.      iDr0          DWORD ?
  113.      iDr1          DWORD ?
  114.      iDr2          DWORD ?
  115.      iDr3          DWORD ?
  116.      iDr6          DWORD ?
  117.      iDr7          DWORD ?
  118.      FloatSave     FLOATING_SAVE_AREA <>
  119.      regGs         DWORD ?
  120.      regFs         DWORD ?
  121.      regEs         DWORD ?
  122.      regDs         DWORD ?
  123.      regEdi        DWORD ?
  124.      regEsi        DWORD ?
  125.      regEbx        DWORD ?
  126.      regEdx        DWORD ?
  127.      regEcx        DWORD ?
  128.      regEax        DWORD ?
  129.      regEbp        DWORD ?
  130.      regEip        DWORD ?
  131.      regCs         DWORD ?
  132.      regFlag       DWORD ?
  133.      regEsp        DWORD ?
  134.      regSs         DWORD ?
  135.      ;ExtendedRegisters BYTE MAXIMUM_SUPPORTED_EXTENSION DUP (?)
  136.    _CONTEXT ENDS
  137. ;-------------------------------------------------------------------------------
  138. ;Performs 'riding on the thread' of process specified by procID and which handle
  139. ;is in EBX register.
  140. ;Returns ApiHooks ErrorCodes.
  141.  
  142. RemoteExec9x      PROC   USES ESI, procID, ExpTime, lpBlock, BlockSize, lpCodeEnd
  143.    LOCAL     ErrVal :DWORD
  144.    LOCAL     SuspCnt:DWORD
  145.    LOCAL     TID    :DWORD
  146.    LOCAL     MyTime :DWORD
  147.    LOCAL     MyProcessPriority :DWORD
  148.    LOCAL     MyThreadPriority :DWORD
  149.    LOCAL     hThreadTIDField[MAX_HTIDTHREAD*2+1] :HANDLE  ;array of handles and tids
  150.    LOCAL     mcontext :_CONTEXT
  151.    LOCAL     context  :_CONTEXT
  152.  
  153.    ;initialize local variables
  154.    SUB       EAX, EAX
  155.    oMOV      ErrVal, ErrorRemoteExec
  156.    AND       MyProcessPriority, EAX
  157.    MOV       MyThreadPriority, THREAD_PRIORITY_ERROR_RETURN
  158.    oMOV      MyTime, ExpTime
  159.  
  160.  
  161.    LEA       ESI, hThreadTIDField
  162.    sWin32    FindThread,   THREAD_SUSPEND_RESUME OR THREAD_GET_CONTEXT OR \
  163.                            THREAD_SET_CONTEXT OR THREAD_QUERY_INFORMATION,\
  164.                            EAX,\     ;null inheritance
  165.                            procID,\
  166.                            ESI       ;array
  167.    TEST      EAX, EAX
  168.    JE        Re9xFailed    ;can't find thread suitable for riding on -> fail
  169.  
  170.    MOV       TID, ECX      ;returned thread id in ECX
  171.    MOV       ESI, EAX      ;thread handle
  172.    iWin32    SuspendThread, EAX    ;get suspend count
  173.    MOV       SuspCnt, EAX
  174.    INC       EAX
  175.    JNE       @F
  176.    oMOV      SuspCnt, MAXIMUM_SUSPEND_COUNT ;if suspension fails, assume max_susp_count
  177.   @@:
  178.    iWin32    ResumeThread, ESI       ;restore suspend count
  179.  
  180.    MOV       EAX, lpCodeEnd
  181.    MOV       WORD PTR [EAX], 0FEEBH  ;put JMP $ at the end of remote code
  182.  
  183.    ;in EBX is target process handle
  184.    ;write remote block to the process
  185.    iWin32    WriteProcessMemory, EBX, EDI, lpBlock, BlockSize, NULL
  186.    TEST      EAX, EAX
  187.    JE        @F
  188.  
  189. ;=====================================
  190.    ;JMP $ at the end of remote code requires my and target process and
  191.    ;thread priorities to be equal. If my prioirities would be less I
  192.    ;couldn't control the target thread
  193.  
  194.    ;adjust my process priority according to target process' priority
  195.  
  196.    iWin32    GetPriorityClass, EBX   ;get target's priority
  197.    TEST      EAX, EAX
  198.    JE        @F                ;can't get priority -> fail
  199.    PUSH      EAX
  200.    iWin32    GetPriorityClass, CurrentProcess ;get this process priority
  201.    TEST      EAX, EAX
  202.    POP       EDX               ;TargetProcessPriority
  203.    JE        @F                ;can't get priority -> fail
  204.    CMP       EAX, EDX          ;compare process priorities
  205.    JE        ThrPri            ;if equal compare thread priorities
  206.    MOV       MyProcessPriority, EAX
  207.    iWin32    SetPriorityClass, CurrentProcess, EDX
  208.    TEST      EAX, EAX
  209.   @@:
  210.    JE        Re9xClose
  211.  
  212.    ;adjust my thread priority according to target thread's priority
  213.  
  214.  ThrPri:
  215.    iWin32    GetThreadPriority, ESI
  216.    CMP       EAX, MyThreadPriority ;== THREAD_PRIORITY_ERROR_RETURN
  217.    JE        @F                ;can't get priority -> fail
  218.    PUSH      EAX
  219.    iWin32    GetThreadPriority, CurrentThread
  220.    CMP       EAX, MyThreadPriority ;== THREAD_PRIORITY_ERROR_RETURN
  221.    POP       EDX               ;TargetThreadPriority
  222.    JE        @F                ;can't get priority -> fail
  223.    CMP       EAX, EDX
  224.    JE        WakeUp
  225.    MOV       MyThreadPriority, EAX
  226.    iWin32    SetThreadPriority, CurrentThread, EDX
  227.    TEST      EAX, EAX
  228.   @@:
  229.    JE        RetProcessPriority  ;if failed return process priority
  230. ;=====================================
  231.  
  232.    ;wake up target thread (affects GUI threads only)
  233.   WakeUp:
  234.    iWin32i   PostThreadMessage, TID, WM_NCACTIVATE, TRUE, EAX
  235.  
  236.    ;save target thread's context
  237.    LEA       EAX, context          ;original context
  238.    PUSHp     ESI, EDI
  239.    MOV       (_CONTEXT PTR [EAX]).ContextFlags, CONTEXT_INTEGER OR CONTEXT_CONTROL ;CONTEXT_FULL OR CONTEXT_EXTENDED_REGISTERS OR CONTEXT_FLOATING_POINT OR CONTEXT_DEBUG_REGISTERS
  240.    PUSH      EAX
  241.    iWin32    GetThreadContext, ESI, EAX
  242.    POP       ESI
  243.    LEA       EDI, mcontext         ;working context
  244.    oMOV      ECX, _CONTEXT/4       ;copy context
  245.    MOV       EDX, EDI
  246.    REP       MOVSD
  247.    TEST      EAX, EAX
  248.    POPc      ESI, EDI
  249.    JE        RetThreadPriority     ;if failed return thread and process priorities
  250.  
  251.    ASSUME    EDX: PTR _CONTEXT
  252.    SUB       [EDX].regEsp, 50H     ;for sure eat some target stack
  253.    XOR       [EDX].ContextFlags,    CONTEXT_INTEGER XOR CONTEXT_i386  ;INTEGER OFF
  254.    MOV       [EDX].regEip, EDI
  255.    iWin32    SetThreadContext, ESI, EDX
  256.    ASSUME    EDX: NOTHING
  257.    XOR       mcontext.ContextFlags, CONTEXT_INTEGER XOR CONTEXT_i386  ;INTEGER ON
  258.    TEST      EAX, EAX
  259.    JE        RetThreadPriority     ;if failed return my priorities
  260.  
  261.    MOV       EAX, lpBlock
  262.    ADD       lpCodeEnd, EDI
  263.    SUB       lpCodeEnd, EAX        ;EIP of CodeEnd in the target
  264.  
  265.    PUSH      EDI
  266.    LEA       EDI, mcontext
  267.    ASSUME    EDI: PTR _CONTEXT
  268.  
  269.   @@:
  270.    iWin32    ResumeThread, ESI
  271.    DEC       EAX
  272.    JG        @B                    ;resume until suspend count == 0
  273.    iWin32    Sleep, 256            ;run the thread for 256 ms
  274.    iWin32    SuspendThread, ESI    ;and suspend it for the next analysis
  275.  
  276.    iWin32    GetThreadContext, ESI, EDI
  277.   NeverEnding:
  278.    MOV       EAX, [EDI].regEip
  279.    CMP       EAX, lpCodeEnd        ;is EIP at CodeEnd (JMP $) ?
  280.    JE        WorkEnd               ;yes done
  281.    CMP       ExpTime, INFINITE     ;user gave us time?
  282.    JE        @B                    ;yes -> go on
  283.    SUB       MyTime, 256           ;subtract 256 ms  from time counter
  284.    JNLE      @B                    ;still some ms? yes-> go on
  285.    JMP       RetContext            ;no -> return all
  286.  
  287.   WorkEnd:
  288.    MOV       EAX, [EDI].regEax     ;update thread's EAX according returned ECX
  289.    MOV       ECX, [EDI].regEcx     ;ECX == original EAX (at thread entry)
  290.    MOV       ErrVal, EAX           ;return value
  291.    MOV       context.regEax, ECX   ;important for the thread which was awaked
  292.  
  293.   RetContext:
  294.    LEA       EAX, context
  295.    POP       EDI
  296.    ASSUME    EDI: NOTHING
  297.    iWin32    SetThreadContext, ESI, EAX   ;return original context
  298.  
  299.   RetThreadPriority:
  300.    MOV       EAX, MyThreadPriority
  301.    CMP       EAX, THREAD_PRIORITY_ERROR_RETURN
  302.    JE        RetProcessPriority
  303.    iWin32    SetThreadPriority, CurrentThread, EAX  ;return my thread priority
  304.  
  305.   RetProcessPriority:
  306.    MOV       EAX, MyProcessPriority
  307.    TEST      EAX, EAX
  308.    JE        Re9xClose
  309.    iWin32    SetPriorityClass, CurrentProcess , EAX  ;return my process priority
  310.  
  311.   Re9xClose:                       ;evaluate error code
  312.    INC       MyTime
  313.    JE        NotExpired
  314.    DEC       MyTime
  315.    JNL       NotExpired
  316.    oMOV      ErrVal, ErrorTimeOut
  317.  
  318.   NotExpired:
  319.   @@:
  320.    DEC       SuspCnt
  321.    JLE       Re9xClThr
  322.    iWin32    SuspendThread, ESI    ;return original suspend count
  323.    JMP       @B
  324.  
  325.   Re9xClThr:
  326.    LEA       ESI, hThreadTIDField
  327.    sWin32    DeSuspend, ESI, -1    ;desuspend all threads in target
  328.  
  329.   Re9xFailed:
  330.   @@:
  331.    LODSD
  332.    TEST      EAX, EAX
  333.    JE        ClDone
  334.    iWin32    CloseHandle, EAX      ;close all threads
  335.    LODSD
  336.    JMP       @B
  337.  
  338.   ClDone:
  339.    sWin32    RemoteFree, EDI       ;free memory allocated in target
  340.    TEST      EAX, EAX
  341.    JNE       @F
  342.    CMP       ErrVal, ErrorSuccess  ;evaluate error code
  343.    JNE       @F
  344.    oMOV      ErrVal, ErrorRemoteFree
  345.   @@:
  346.    MOV       EAX, ErrVal           ;return it
  347.    RET
  348. RemoteExec9x      ENDP
  349. ;-------------------------------------------------------------------------------
  350. ;Tries to find thread suitable for executing remote code.
  351. ;Such a thread must be 32bit and FS must not be null.
  352. ;Returns thread handle if all went OK and NULL if there was an error.
  353. ;Returns thread id in ECX.
  354.  
  355.  FindThread        PROC  USES EBX ESI EDI, fdwAccess, fInherit, IDProcess, hThreadTIDField
  356.    LOCAL     context :_CONTEXT
  357.  
  358.    MOV       ESI, hThreadTIDField
  359.    LEA       EDI, context
  360.    ASSUME    EDI: PTR _CONTEXT
  361.  
  362.    sWin32    OpenAllThreads, fdwAccess, fInherit, IDProcess, ESI
  363.    TEST      EAX, EAX
  364.    JNE       Unsuccess   ;can't open all IDProcess' threads
  365.  
  366.    ;watch thread CS and FS values
  367.    MOV       [EDI].ContextFlags, CONTEXT_CONTROL OR CONTEXT_SEGMENTS
  368.  
  369.    ;1st suspend all the threads
  370.   Susp:
  371.    LODSD
  372.    TEST      EAX, EAX
  373.    JE        ChooseCandidate
  374.    MOV       EBX, EAX
  375.    LODSD
  376.    iWin32    SuspendThread, EBX
  377.    INC       EAX
  378.    JNE       Susp
  379.    SUB       ESI, 8     ;cut this thread (handle+tid) from array
  380.   DesuspIt:
  381.    ;desuspend all threads in array, which were suspended above
  382.    sWin32    DeSuspend, hThreadTIDField, ESI
  383.   Unsuccess:
  384.    SUB       EAX, EAX   ;return NULL
  385.    JMP       Success
  386.   DesuspAll:
  387.    OR        ESI, -1      ;till the end of array
  388.    JMP       DesuspIt
  389.  
  390.    ;2nd now select first thread with suitable CS and FS
  391.   ChooseCandidate:
  392.    MOV       ESI, hThreadTIDField   ;start
  393.   @@:
  394.    LODSD
  395.    MOV       EBX, EAX     ;save handle
  396.    TEST      EAX, EAX
  397.    JE        DesuspAll    ;at the end and none was chosen
  398.    LODSD
  399.    PUSH      EAX
  400.    iWin32    GetThreadContext, EBX, EDI
  401.    TEST      EAX, EAX
  402.    POP       ECX
  403.    JE        @B           ;can't get context -> explore next thread
  404.    MOV       EDX, CS
  405.    CMP       WORD PTR context.regFs, 0    ;thread FS != 0
  406.    JE        @B
  407.    CMP       DX, WORD PTR context.regCs   ;thread CS == myCS
  408.    JNE       @B
  409.    MOV       EAX, EBX      ;return thread handle
  410.   Success:
  411.    RET
  412.    ASSUME    EDI: NOTHING
  413.   FindThread       ENDP
  414. ;-------------------------------------------------------------------------------
  415. ;Tries to open all threads of given 9x process.
  416. ;Fills StoreHandlesIDs array with handle, id, handle, id, ... and terminates
  417. ;the chain with NULL handle.
  418. ;Returns  -1 if there was an error.
  419.  
  420.  OpenAllThreads9x  PROC USES EBX ESI EDI, fdwAccess, fInherit, IDProcess, StoreHandlesIDs
  421.    LOCAL     ThrCnt :DWORD
  422.    LOCAL     thread :THREADENTRY32
  423.  
  424.    MOV       EDI, StoreHandlesIDs
  425.    ;make thread snapshot
  426.    sWin32    CreateToolhelp32Snapshot, TH32CS_SNAPTHREAD, IDProcess
  427.    MOV       EBX, EAX
  428.    CMP       EAX, -1
  429.    JE        ThrExit
  430.    oMOV      ThrCnt, MAX_HTIDTHREAD   ;initialize thread counter (array size)
  431.    ASSUME    ESI: PTR THREADENTRY32
  432.    LEA       ESI, thread
  433.    oMOV      [ESI].dwSize, SIZEOF THREADENTRY32
  434.    sWin32    Thread32First, EBX, ESI
  435.   @@:
  436.    TEST      EAX, EAX
  437.    JE        ThrClose
  438.    MOV       EAX, [ESI].th32OwnerProcessID
  439.    CMP       EAX, IDProcess
  440.    JNE       ThrNext
  441.    sWin32    OpenThread9x, fdwAccess, fInherit, [ESI].th32ThreadID
  442.    TEST      EAX, EAX
  443.    JE        ThrCloseFail   ;if can't open any of ps' threads -> fin
  444.    STOSD
  445.    MOV       EAX, [ESI].th32ThreadID
  446.    STOSD
  447.    SUB       EAX, EAX
  448.    DEC       ThrCnt         ;Too many threads
  449.    JLE       ThrClose       ;quit but don't fail
  450.   ThrNext:
  451.    sWin32    Thread32Next, EBX, ESI
  452.    JMP       @B
  453.   ThrCloseFail:
  454.    OR        EAX, -1        ;failed -> return -1
  455.   ThrClose:
  456.    PUSH      EAX
  457.    iWin32    CloseHandle, EBX    ;close snapshot
  458.    POP       EAX
  459.   ThrExit:
  460.    AND       DWORD PTR [EDI], 0 ;NULL handle at the end of OPENED thread handles in the array
  461.    RET
  462.  OpenAllThreads9x  ENDP
  463. ;-------------------------------------------------------------------------------
  464. ;Tries to open all threads of given NT process.
  465. ;Fills StoreHandlesIDs array with handle, id, handle, id, ... and terminates
  466. ;the chain with NULL handle.
  467. ;Returns  -1 if there was an error.
  468.  
  469.  OpenAllThreadsNT PROC USES EBX ESI EDI, fdwAccess, fInherit, IDProcess, StoreHandlesIDs
  470.    LOCAL     ThrCnt :DWORD
  471.  
  472.    oMOV      ThrCnt, MAX_HTIDTHREAD ;initialize thread counter (array size)
  473.    oMOV      EBX, START_SIZE_FOR_NTQUERY
  474.  
  475.   @@:
  476.    MOV       EDI, StoreHandlesIDs     ;array: handle, id, handle, id, ...
  477.    sWin32    RemoteAlloc9x, EBX, NULL ;allocate memory for ntquery
  478.    MOV       ESI, EAX
  479.    DEC       EAX      ;return -1 if alloc failed
  480.    JL        ThrExit
  481.    sWin32    NtQuerySystemInformation, SystemProcessInformation, ESI, EBX, NULL
  482.    CMP       EAX, STATUS_INFO_LENGTH_MISMATCH
  483.    JNE       @F           ;native api returned NTSTATUS
  484.    sWin32    RemoteFree9x, ESI        ;free allocated memory and allocate
  485.    ADD       EBX, DELTA_SIZE_FOR_NTQUERY ;more memory
  486.    JMP       @B
  487.   @@:
  488.    TEST      EAX, EAX
  489.    JL        ThrExit0                 ;ntquery failed -> return -1
  490.                                       ;there are too many processes and no memory
  491.    MOV       ECX, ESI
  492.    ASSUME    ECX  :PTR SYSTEM_PROCESS_INFORMATION
  493.    MOV       EBX, IDProcess
  494.    JMP       ThreadFirst   ;assume that there is at least 1 (this) process in the system
  495.   NextProc:
  496.    CMP       [ECX].SizeOfBlock, 0  ;info ends?
  497.    JE        ProcInfoEnd
  498.    ADD       ECX, [ECX].SizeOfBlock ;ECX points to the next block
  499.   ThreadFirst:
  500.    CMP       EBX, [ECX].ProcessId   ;block.pid == parameter IDProcess ?
  501.    JNE       NextProc
  502.    MOV       EDX, SYSTEM_PROCESS_INFORMATION.ThreadInformation + SYSTEM_THREAD_INFORMATION.ClientId.UniqueThread
  503.    ThreadInfoStart EQU BYTE PTR $-4      ;This is patched in DllMain if running in NT4
  504.   ThreadNext:
  505.    DEC       [ECX].ThreadCount
  506.    JL        ProcInfoEnd
  507.    ASSUME    ECX :NOTHING
  508.    MOV       EAX, [ECX+EDX]    ;ThreadId
  509.    STOSD                       ;store it in the array
  510.    STOSD
  511.    DEC       ThrCnt
  512.    JLE       ProcInfoEnd
  513.    ADD       EDX, SIZEOF SYSTEM_THREAD_INFORMATION
  514.    JMP       ThreadNext
  515.   ProcInfoEnd:
  516.    SUB       EAX, EAX
  517.    STOSD                       ;store NULL handle (end of array)
  518.    MOV       EDI, StoreHandlesIDs
  519.   @@:
  520.    MOV       EAX, [EDI]        ;get TID
  521.    TEST      EAX, EAX          ; == NULL end
  522.    JE        ThrExit0
  523.    sWin32    OpenThreadNT, fdwAccess, fInherit, EBX, EAX
  524.    TEST      EAX, EAX
  525.    JE        ThrExit1   ;if can't open any of ps' threads -> fin
  526.    STOSD                       ;store thread handle
  527.    ADD       EDI, 4            ;skip TID
  528.    JMP       @B
  529.   ThrExit1:
  530.    OR        EAX, -1           ;failed -> return -1
  531.   ThrExit0:
  532.    PUSH      EAX
  533.    sWin32    RemoteFree9x, ESI  ;free ntquery memo
  534.    POP       EAX
  535.   ThrExit:
  536.    AND       DWORD PTR [EDI], 0 ;NULL handle at the end of OPENED thread handles in the array
  537.    RET
  538.  OpenAllThreadsNT  ENDP
  539. ;-------------------------------------------------------------------------------
  540. ;Desuspends opened threads. Handles are in hthreadTIDField array (handle, id,
  541. ;handle, id,...). Last is NULL handle.
  542. ;Returns void.
  543.  
  544.   DeSuspend        PROC USES ESI, hFrom, hTo
  545.    MOV       ESI, hFrom   ;start here
  546.   @@:
  547.    CMP       ESI, hTo     ;end here
  548.    JAE       DeSuspended
  549.    LODSD
  550.    TEST      EAX, EAX     ;if hThread == NULL end
  551.    JE        DeSuspended
  552.    iWin32    ResumeThread, EAX
  553.    LODSD
  554.    JMP       @B
  555.   DeSuspended:
  556.    RET
  557.   DeSuspend        ENDP
  558. ;-------------------------------------------------------------------------------
  559. ;Opens Windows 9x thread represented by thread id. Used is routine at
  560. ;OpenProcess+24H. OpenThread API is present in Windows Millenium only.
  561. ;Returns thread handle if all went OK, NULL if there was an error.
  562. ;Based on ATM method (c) Enrico Del Fante.
  563.  
  564.   OpenThread9x     PROC fdwAccess, fInherit, IDThread
  565.    SUB       EAX, EAX                 ;NULL
  566.    MOV       EDX, 0                   ;Was "OpenThread" routine found?
  567.    W9xOpenThread  EQU DWORD PTR $-4
  568.    TEST      EDX, EDX
  569.    JE        @F                       ;No -> return NULL
  570.    MOV       EAX, 0
  571.    Obsfucator     EQU DWORD PTR $-4
  572.    XOR       EAX, IDThread            ;Thread Database = ThreadId ^ Obsfucator
  573.                                       ;must be in EAX
  574.    sWin32    EDX, fdwAccess, fInherit, IDThread
  575.   @@:
  576.    RET
  577.   OpenThread9x     ENDP
  578. ;-------------------------------------------------------------------------
  579. ;Opens Windows NT thread represented by client id.
  580. ;Inheritance is not handled (if fInherit is TRUE, put 2 into oa.Attributes).
  581. ;Client id == process id & thread id.
  582. ;However, thread can opened by thread id only when is process id part
  583. ;of client id = 0.
  584. ;Returns thread handle if all went OK, NULL if there was an error.
  585.  
  586.   OpenThreadNT     PROC USES EDI, fdwAccess, fInherit, CID :CLIENT_ID
  587.    LOCAL     hThread :HANDLE
  588.    LOCAL     oa :OBJECT_ATTRIBUTES
  589.  
  590.    LEA       EDX, CID
  591.    LEA       EDI, oa
  592.    PUSHc     fdwAccess, EDI, EDX    ;push parameters for NtOpenThread
  593.    oMOV      EAX, SIZEOF oa   ;initialize object attributes
  594.    STOSD
  595.    SUB       EAX, EAX
  596.    ZeroBlockSize = (SIZEOF oa - SIZEOF oa.Length_)/4
  597.    oMOV      ECX, ZeroBlockSize
  598.    REP       STOSD
  599.    PUSH      EDI             ;push 1st parameter: address of hThread
  600.    STOSD                     ;hThread = 0
  601.    sWin32    NtOpenThread
  602.    MOV       EAX, hThread    ;here is no check for error
  603.    RET                       ;hThread == 0 is assumed if there was an error
  604.   OpenThreadNT     ENDP
  605. ;-------------------------------------------------------------------------------