1. To visit protected / private sections of the forum you must be connected with your user account. If you are not yet a member of our forum, you can create it now for free!.

User Tag List

Thread: ror 13

Results 1 to 6 of 6

  1. #1
    The Executer's Avatar
    Senior Member
    Join Date May 2010
    Location cs:0100
    Posts 502
    Like (Stats)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    0 Post(s)

    ror 13

    might help someone to prevent recursion and not just finding api.
    Code:
    hashfunc:         ;input: esi pointing to string 
    xor edx,edx       ;output: eax will return hash as DWORD value
    label1:
    xor eax,eax
    lodsb
    test al,al
    jz last
    ror edx,0xd
    add edx,eax
    jmp label1
    last:
    mov eax,edx
    ret
  2. #2
    Erik_v4's Avatar
    Senior Member
    Join Date Jun 2010
    Location Jordan
    Posts 181
    Like (Stats)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    0 Post(s)
    ror or rot?!
  3. #3
    The Executer's Avatar
    Senior Member
    Join Date May 2010
    Location cs:0100
    Posts 502
    Like (Stats)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    0 Post(s)
    ROR is rotation in asm. 0xD is 13, rotate 13bits right. (not the same one as ROT13 )
  4. #4
    mickylee's Avatar
    Member
    Join Date Nov 2012
    Posts 31
    Like (Stats)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    1 Post(s)
    Code:
    ;-----------------------------------------------------------------------------;
    ; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
    ; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
    ; Version: 1.0 (24 July 2009)
    ; Size: 137 bytes
    ;-----------------------------------------------------------------------------;
    
    [BITS 32]
    
    ; Input: The hash of the API to call and all its parameters must be pushed onto stack.
    ; Output: The return value from the API call will be in EAX.
    ; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention)
    ; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered.
    ; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.
    ; Note: This function is unable to call forwarded exports.
    
    api_call:
      pushad                 ; We preserve all the registers for the caller, bar EAX and ECX.
      mov ebp, esp           ; Create a new stack frame
      xor edx, edx           ; Zero EDX
      mov edx, [fs:edx+48]   ; Get a pointer to the PEB
      mov edx, [edx+12]      ; Get PEB->Ldr
      mov edx, [edx+20]      ; Get the first module from the InMemoryOrder module list
    next_mod:                ;
      mov esi, [edx+40]      ; Get pointer to modules name (unicode string)
      movzx ecx, word [edx+38] ; Set ECX to the length we want to check 
      xor edi, edi           ; Clear EDI which will store the hash of the module name
    loop_modname:            ;
      xor eax, eax           ; Clear EAX
      lodsb                  ; Read in the next byte of the name
      cmp al, 'a'            ; Some versions of Windows use lower case module names
      jl not_lowercase       ;
      sub al, 0x20           ; If so normalise to uppercase
    not_lowercase:           ;
      ror edi, 13            ; Rotate right our hash value
      add edi, eax           ; Add the next byte of the name
      loop loop_modname      ; Loop untill we have read enough
      ; We now have the module hash computed
      push edx               ; Save the current position in the module list for later
      push edi               ; Save the current module hash for later
      ; Proceed to itterate the export address table, 
      mov edx, [edx+16]      ; Get this modules base address
      mov eax, [edx+60]      ; Get PE header
      add eax, edx           ; Add the modules base address
      mov eax, [eax+120]     ; Get export tables RVA
      test eax, eax          ; Test if no export address table is present
      jz get_next_mod1       ; If no EAT present, process the next module
      add eax, edx           ; Add the modules base address
      push eax               ; Save the current modules EAT
      mov ecx, [eax+24]      ; Get the number of function names  
      mov ebx, [eax+32]      ; Get the rva of the function names
      add ebx, edx           ; Add the modules base address
      ; Computing the module hash + function hash
    get_next_func:           ;
      jecxz get_next_mod     ; When we reach the start of the EAT (we search backwards), process the next module
      dec ecx                ; Decrement the function name counter
      mov esi, [ebx+ecx*4]   ; Get rva of next module name
      add esi, edx           ; Add the modules base address
      xor edi, edi           ; Clear EDI which will store the hash of the function name
      ; And compare it to the one we want
    loop_funcname:           ;
      xor eax, eax           ; Clear EAX
      lodsb                  ; Read in the next byte of the ASCII function name
      ror edi, 13            ; Rotate right our hash value
      add edi, eax           ; Add the next byte of the name
      cmp al, ah             ; Compare AL (the next byte from the name) to AH (null)
      jne loop_funcname      ; If we have not reached the null terminator, continue
      add edi, [ebp-8]       ; Add the current module hash to the function hash
      cmp edi, [ebp+36]      ; Compare the hash to the one we are searchnig for 
      jnz get_next_func      ; Go compute the next function hash if we have not found it
      ; If found, fix up stack, call the function and then value else compute the next one...
      pop eax                ; Restore the current modules EAT
      mov ebx, [eax+36]      ; Get the ordinal table rva      
      add ebx, edx           ; Add the modules base address
      mov cx, [ebx+2*ecx]    ; Get the desired functions ordinal
      mov ebx, [eax+28]      ; Get the function addresses table rva  
      add ebx, edx           ; Add the modules base address
      mov eax, [ebx+4*ecx]   ; Get the desired functions RVA
      add eax, edx           ; Add the modules base address to get the functions actual VA
      ; We now fix up the stack and perform the call to the desired function...
    finish:
      mov [esp+36], eax      ; Overwrite the old EAX value with the desired api address for the upcoming popad
      pop ebx                ; Clear off the current modules hash
      pop ebx                ; Clear off the current position in the module list
      popad                  ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
      pop ecx                ; Pop off the origional return address our caller will have pushed
      pop edx                ; Pop off the hash value our caller will have pushed
      push ecx               ; Push back the correct return value
      jmp eax                ; Jump into the required function
      ; We now automagically return to the correct caller...
    get_next_mod:            ;
      pop eax                ; Pop off the current (now the previous) modules EAT
    get_next_mod1:           ;
      pop edi                ; Pop off the current (now the previous) modules hash
      pop edx                ; Restore our position in the module list
      mov edx, [edx]         ; Get the next module
      jmp short next_mod     ; Process this module
    A very elegant solution for your shellcode needs. As the instructions state: Simply pass the parameters to the Windows API you want to call on the stack, then push the hash value for the API you want to call and this code will find and transfer control to it.

    For calculating your hash values using ror 13:

    Code:
    #=============================================================================#
    # This script can detect hash collisions between exported API functions in 
    # multiple modules by either scanning a directory tree or just a single module.
    # This script can also just output the correct hash value for any single API
    # function for use with the 'api_call' function in 'block_api.asm'.
    #
    # Example: Detect fatal collisions against all modules in the C drive:
    #     >hash.py /dir c:\
    #
    # Example: List the hashes for all exports from kernel32.dll (As found in 'c:\windows\system32\')
    #     >hash.py /mod c:\windows\system32\ kernel32.dll
    #
    # Example: Simply print the correct hash value for the function kernel32.dll!WinExec
    #     >hash.py kernel32.dll WinExec
    #
    # Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
    #=============================================================================#
    from sys import path
    import os, time, sys
    
    # Modify this path to pefile to suit your machine...
    pefile_path = "D:\\Development\\Frameworks\\pefile\\"
    
    path.append( pefile_path )
    import pefile
    #=============================================================================#
    collisions = [  ( 0x006B8029, "ws2_32.dll!WSAStartup" ),
                    ( 0xE0DF0FEA, "ws2_32.dll!WSASocketA" ),
                    ( 0x6737DBC2, "ws2_32.dll!bind" ),
                    ( 0xFF38E9B7, "ws2_32.dll!listen" ),
                    ( 0xE13BEC74, "ws2_32.dll!accept" ),
                    ( 0x614D6E75, "ws2_32.dll!closesocket" ),
                    ( 0x6174A599, "ws2_32.dll!connect" ),
                    ( 0x5FC8D902, "ws2_32.dll!recv" ),
                    ( 0x5F38EBC2, "ws2_32.dll!send" ),
                    
                    ( 0x5BAE572D, "kernel32.dll!WriteFile" ),
                    ( 0x4FDAF6DA, "kernel32.dll!CreateFileA" ),
                    ( 0x13DD2ED7, "kernel32.dll!DeleteFileA" ),
                    ( 0xE449F330, "kernel32.dll!GetTempPathA" ),
                    ( 0x528796C6, "kernel32.dll!CloseHandle" ),
                    ( 0x863FCC79, "kernel32.dll!CreateProcessA" ),
                    ( 0xE553A458, "kernel32.dll!VirtualAlloc" ),
                    ( 0x300F2F0B, "kernel32.dll!VirtualFree" ),
                    ( 0x0726774C, "kernel32.dll!LoadLibraryA" ),
                    ( 0x7802F749, "kernel32.dll!GetProcAddress" ),
                    ( 0x601D8708, "kernel32.dll!WaitForSingleObject" ),
                    ( 0x876F8B31, "kernel32.dll!WinExec" ),
                    ( 0x9DBD95A6, "kernel32.dll!GetVersion" ),
                    ( 0xEA320EFE, "kernel32.dll!SetUnhandledExceptionFilter" ),
                    ( 0x56A2B5F0, "kernel32.dll!ExitProcess" ),
                    ( 0x0A2A1DE0, "kernel32.dll!ExitThread" ),
                    
                    ( 0x6F721347, "ntdll.dll!RtlExitUserThread" ),
                    
                    ( 0x23E38427, "advapi32.dll!RevertToSelf" )
                  ]
    
    collisions_detected = {}
    modules_scanned = 0
    functions_scanned = 0
    #=============================================================================#
    def ror( dword, bits ):
      return ( dword >> bits | dword << ( 32 - bits ) ) & 0xFFFFFFFF
    #=============================================================================#
    def unicode( string, uppercase=True ):
      result = "";
      if uppercase:
        string = string.upper()
      for c in string:
        result += c + "\x00"
      return result
    #=============================================================================#
    def hash( module, function, bits=13, print_hash=True ):
      module_hash = 0
      function_hash = 0
      for c in unicode( module + "\x00" ):
        module_hash  = ror( module_hash, bits )
        module_hash += ord( c )
      for c in str( function + "\x00" ):
        function_hash  = ror( function_hash, bits )
        function_hash += ord( c )
      h = module_hash + function_hash & 0xFFFFFFFF
      if print_hash:
        print "[+] 0x%08X = %s!%s" % ( h, module.lower(), function )
      return h
    #=============================================================================#
    def scan( dll_path, dll_name, print_hashes=False, print_collisions=True ):
      global modules_scanned
      global functions_scanned
      try:
        dll_name = dll_name.lower()
        modules_scanned += 1
        pe = pefile.PE( os.path.join( dll_path, dll_name ) )
        for export in pe.DIRECTORY_ENTRY_EXPORT.symbols:
          if export.name is None:
            continue
          h = hash( dll_name, export.name, print_hash=print_hashes )
          for ( col_hash, col_name ) in collisions:
            if col_hash == h and col_name != "%s!%s" % (dll_name, export.name):
              if h not in collisions_detected.keys():
                collisions_detected[h] = []
              collisions_detected[h].append( (dll_path, dll_name, export.name) )
              break
          functions_scanned += 1
      except:
        pass
    #=============================================================================#
    def scan_directory( dir ):
      for dot, dirs, files in os.walk( dir ):
        for file_name in files:
          if file_name[-4:] == ".dll":# or file_name[-4:] == ".exe":
            scan( dot, file_name )
      print "\n[+] Found %d Collisions.\n" % ( len(collisions_detected) )
      for h in collisions_detected.keys():
        for (col_hash, col_name ) in collisions:
          if h == col_hash:
            detected_name = col_name
            break
        print "[!] Collision detected for 0x%08X (%s):" % ( h, detected_name )
        for (collided_dll_path, collided_dll_name, collided_export_name) in collisions_detected[h]:
          print "\t%s!%s (%s)" % ( collided_dll_name, collided_export_name, collided_dll_path )
      print "\n[+] Scanned %d exported functions via %d modules.\n" % ( functions_scanned, modules_scanned )
    #=============================================================================#
    def main( argv=None ):
      if not argv:
        argv = sys.argv
      try:
        if len( argv ) == 1:
          print "Usage: hash.py [/dir <path>] | [/mod <path> <module.dll>] | [<module.dll> <function>]"
        else:
          print "[+] Ran on %s\n" % (  time.asctime( time.localtime() ) )
          if argv[1] == "/dir":
            print "[+] Scanning directory '%s' for collisions..." % argv[2]
            scan_directory( argv[2] )
          elif argv[1] == "/mod":
            print "[+] Scanning module '%s' in directory '%s'..." % ( argv[3], argv[2] )
            scan( argv[2], argv[3], print_hashes=True )
          else:
            hash( argv[1], argv[2] )
      except Exception, e:
        print "[-] ", e
    #=============================================================================#
    if __name__ == "__main__":
      main()
    #=============================================================================#
    "I have always loved truth so passionately that I have often resorted to lying as a way of introducing it into the minds which were ignorant of its charms"
  5. #5
    The Executer's Avatar
    Senior Member
    Join Date May 2010
    Location cs:0100
    Posts 502
    Like (Stats)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    0 Post(s)
    i dont think hash collisions can happen until win8 for the most used API's for us malware authors.
    the script is handy, too bad i made one in C. :/
  6. #6
    mickylee's Avatar
    Member
    Join Date Nov 2012
    Posts 31
    Like (Stats)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    1 Post(s)
    i dont think hash collisions can happen until win8 for the most used API's for us malware authors.
    the script is handy, too bad i made one in C. :/
    hehe I had originally done the same thing until I found his python script
    "I have always loved truth so passionately that I have often resorted to lying as a way of introducing it into the minds which were ignorant of its charms"

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts