Showing posts with label reverse engineering. Show all posts
Showing posts with label reverse engineering. Show all posts

Thursday, March 06, 2008

Digging up system call ordinals

Today I was hacking a small tool and I needed a list of all the system call ordinals corresponding to the APIs exported by NTDLL.DLL. A bit of googling didn't come up with anything too interesting so I wrote a small IDAPython script to harvest them out of a disassembly of NTDLL.DLL.
The script will simply iterate through every segment and every function and try to find the byte pattern corresponding to the prolog of API functions calling the stub doing the SYSENTER, SYSCALL or INT 2Eh.
At least in Windows XP SP2 they will have the form:

MOV eax, XXwhere XX is the syscall ordinal
MOV edx, 7FFE0300hthe stub doing the transition to kernel mode, the actual code reached depends on the underlying processor
CALL [edx]


Those instructions correspond to the byte sequence 'B8 ? 00 00 00 BA 00 03 FE 7F'. I'll just tell IDAPython to look for it at the beginning of each function and, if found, I'll extract the value of the system call ordinal and the name of the function and print a list of them:

syscall_ordinal_code = 'b8 ? 00 00 00 ba 00 03 fe 7f'

for seg in Segments():
  for func in Functions(seg, SegEnd(seg)):
    address = FindBinary(func, SEARCH_DOWN, syscall_ordinal_code)
    if address == func:
      print '%08x: Syscall ordinal %04x for %s (%s)' % (
        func, Dword(func+1), Name(func), Comment(func))


And the outcome of running the script on IDA with NTDLL.DLL looks like this:

7c90d379: Syscall ordinal 0000 for ZwAcceptConnectPort (NtAcceptConnectPort)
7c90d38e: Syscall ordinal 0001 for ZwAccessCheck (NtAccessCheck)
7c90d3a3: Syscall ordinal 0002 for ZwAccessCheckAndAuditAlarm (NtAccessCheckAndAuditAlarm)
7c90d3b8: Syscall ordinal 0003 for ZwAccessCheckByType (NtAccessCheckByType)
7c90d3cd: Syscall ordinal 0004 for ZwAccessCheckByTypeAndAuditAlarm (NtAccessCheckByTypeAndAuditAlarm)
7c90d3e2: Syscall ordinal 0005 for ZwAccessCheckByTypeResultList (NtAccessCheckByTypeResultList)
7c90d3f7: Syscall ordinal 0006 for ZwAccessCheckByTypeResultListAndAuditAlarm (NtAccessCheckByTypeResultListAndAuditAlarm)
7c90d40c: Syscall ordinal 0007 for ZwAccessCheckByTypeResultListAndAuditAlarmByHandle (NtAccessCheckByTypeResultListAndAuditAlarmByHandle)
7c90d421: Syscall ordinal 0008 for ZwAddAtom (NtAddAtom)
7c90d436: Syscall ordinal 0009 for ZwAddBootEntry (NtAddBootEntry)
7c90d44b: Syscall ordinal 000a for ZwAdjustGroupsToken (NtAdjustGroupsToken)
7c90d460: Syscall ordinal 000b for ZwAdjustPrivilegesToken (NtAdjustPrivilegesToken)
7c90d475: Syscall ordinal 000c for ZwAlertResumeThread (NtAlertResumeThread)
7c90d48a: Syscall ordinal 000d for ZwAlertThread (NtAlertThread)
7c90d49f: Syscall ordinal 000e for ZwAllocateLocallyUniqueId (NtAllocateLocallyUniqueId)
7c90d4b4: Syscall ordinal 000f for ZwAllocateUserPhysicalPages (NtAllocateUserPhysicalPages)
7c90d4c9: Syscall ordinal 0010 for ZwAllocateUuids (NtAllocateUuids)
7c90d4de: Syscall ordinal 0011 for ZwAllocateVirtualMemory (NtAllocateVirtualMemory)
7c90d4f3: Syscall ordinal 0012 for ZwAreMappedFilesTheSame (NtAreMappedFilesTheSame)
7c90d508: Syscall ordinal 0013 for ZwAssignProcessToJobObject (NtAssignProcessToJobObject)
7c90d51d: Syscall ordinal 0014 for ZwCallbackReturn (NtCallbackReturn)
7c90d532: Syscall ordinal 0015 for ZwCancelDeviceWakeupRequest (NtCancelDeviceWakeupRequest)
7c90d547: Syscall ordinal 0016 for ZwCancelIoFile (NtCancelIoFile)
7c90d55c: Syscall ordinal 0017 for ZwCancelTimer (NtCancelTimer)
7c90d571: Syscall ordinal 0018 for ZwClearEvent (NtClearEvent)
7c90d586: Syscall ordinal 0019 for ZwClose (NtClose)
7c90d59b: Syscall ordinal 001a for ZwCloseObjectAuditAlarm (NtCloseObjectAuditAlarm)
7c90d5b0: Syscall ordinal 001b for ZwCompactKeys (NtCompactKeys)
7c90d5c5: Syscall ordinal 001c for ZwCompareTokens (NtCompareTokens)
7c90d5da: Syscall ordinal 001d for ZwCompleteConnectPort (NtCompleteConnectPort)
7c90d5ef: Syscall ordinal 001e for ZwCompressKey (NtCompressKey)
7c90d604: Syscall ordinal 001f for ZwConnectPort (NtConnectPort)
7c90d619: Syscall ordinal 0020 for ZwContinue (NtContinue)
7c90d62e: Syscall ordinal 0021 for ZwCreateDebugObject (NtCreateDebugObject)
7c90d643: Syscall ordinal 0022 for ZwCreateDirectoryObject (NtCreateDirectoryObject)
7c90d658: Syscall ordinal 0023 for ZwCreateEvent (NtCreateEvent)
7c90d66d: Syscall ordinal 0024 for ZwCreateEventPair (NtCreateEventPair)
7c90d682: Syscall ordinal 0025 for ZwCreateFile (NtCreateFile)
7c90d697: Syscall ordinal 0026 for ZwCreateIoCompletion (NtCreateIoCompletion)
7c90d6ac: Syscall ordinal 0027 for ZwCreateJobObject (NtCreateJobObject)
7c90d6c1: Syscall ordinal 0028 for ZwCreateJobSet (NtCreateJobSet)
7c90d6d6: Syscall ordinal 0029 for ZwCreateKey (NtCreateKey)
7c90d6eb: Syscall ordinal 002a for ZwCreateMailslotFile (NtCreateMailslotFile)
7c90d700: Syscall ordinal 002b for ZwCreateMutant (NtCreateMutant)
7c90d715: Syscall ordinal 002c for ZwCreateNamedPipeFile (NtCreateNamedPipeFile)
7c90d72a: Syscall ordinal 002d for ZwCreatePagingFile (NtCreatePagingFile)
7c90d73f: Syscall ordinal 002e for ZwCreatePort (NtCreatePort)
7c90d754: Syscall ordinal 002f for ZwCreateProcess (NtCreateProcess)
7c90d769: Syscall ordinal 0030 for ZwCreateProcessEx (NtCreateProcessEx)
7c90d77e: Syscall ordinal 0031 for ZwCreateProfile (NtCreateProfile)
7c90d793: Syscall ordinal 0032 for ZwCreateSection (NtCreateSection)
7c90d7a8: Syscall ordinal 0033 for ZwCreateSemaphore (NtCreateSemaphore)
7c90d7bd: Syscall ordinal 0034 for ZwCreateSymbolicLinkObject (NtCreateSymbolicLinkObject)
7c90d7d2: Syscall ordinal 0035 for ZwCreateThread (NtCreateThread)
7c90d7e7: Syscall ordinal 0036 for ZwCreateTimer (NtCreateTimer)
7c90d7fc: Syscall ordinal 0037 for ZwCreateToken (NtCreateToken)
7c90d811: Syscall ordinal 0038 for ZwCreateWaitablePort (NtCreateWaitablePort)
7c90d826: Syscall ordinal 0039 for ZwDebugActiveProcess (NtDebugActiveProcess)
7c90d83b: Syscall ordinal 003a for ZwDebugContinue (NtDebugContinue)
7c90d850: Syscall ordinal 003b for ZwDelayExecution (NtDelayExecution)
7c90d865: Syscall ordinal 003c for ZwDeleteAtom (NtDeleteAtom)
7c90d87a: Syscall ordinal 003d for ZwDeleteBootEntry (NtDeleteBootEntry)
7c90d88f: Syscall ordinal 003e for ZwDeleteFile (NtDeleteFile)
7c90d8a4: Syscall ordinal 003f for ZwDeleteKey (NtDeleteKey)
7c90d8b9: Syscall ordinal 0040 for ZwDeleteObjectAuditAlarm (NtDeleteObjectAuditAlarm)
7c90d8ce: Syscall ordinal 0041 for ZwDeleteValueKey (NtDeleteValueKey)
7c90d8e3: Syscall ordinal 0042 for ZwDeviceIoControlFile (NtDeviceIoControlFile)
7c90d8f8: Syscall ordinal 0043 for ZwDisplayString (NtDisplayString)
7c90d90d: Syscall ordinal 0044 for ZwDuplicateObject (NtDuplicateObject)
7c90d922: Syscall ordinal 0045 for ZwDuplicateToken (NtDuplicateToken)
7c90d937: Syscall ordinal 0046 for ZwEnumerateBootEntries (NtEnumerateBootEntries)
7c90d94c: Syscall ordinal 0047 for ZwEnumerateKey (NtEnumerateKey)
7c90d961: Syscall ordinal 0048 for ZwEnumerateSystemEnvironmentValuesEx (NtEnumerateSystemEnvironmentValuesEx)
7c90d976: Syscall ordinal 0049 for ZwEnumerateValueKey (NtEnumerateValueKey)
7c90d98b: Syscall ordinal 004a for ZwExtendSection (NtExtendSection)
7c90d9a0: Syscall ordinal 004b for ZwFilterToken (NtFilterToken)
7c90d9b5: Syscall ordinal 004c for ZwFindAtom (NtFindAtom)
7c90d9ca: Syscall ordinal 004d for ZwFlushBuffersFile (NtFlushBuffersFile)
7c90d9df: Syscall ordinal 004e for ZwFlushInstructionCache (NtFlushInstructionCache)
7c90d9f4: Syscall ordinal 004f for ZwFlushKey (NtFlushKey)
7c90da09: Syscall ordinal 0050 for ZwFlushVirtualMemory (NtFlushVirtualMemory)
7c90da1e: Syscall ordinal 0051 for ZwFlushWriteBuffer (NtFlushWriteBuffer)
7c90da33: Syscall ordinal 0052 for ZwFreeUserPhysicalPages (NtFreeUserPhysicalPages)
7c90da48: Syscall ordinal 0053 for ZwFreeVirtualMemory (NtFreeVirtualMemory)
7c90da5d: Syscall ordinal 0054 for ZwFsControlFile (NtFsControlFile)
7c90da72: Syscall ordinal 0055 for ZwGetContextThread (NtGetContextThread)
7c90da87: Syscall ordinal 0056 for ZwGetDevicePowerState (NtGetDevicePowerState)
7c90da9c: Syscall ordinal 0057 for ZwGetPlugPlayEvent (NtGetPlugPlayEvent)
7c90dab1: Syscall ordinal 0058 for ZwGetWriteWatch (NtGetWriteWatch)
7c90dac6: Syscall ordinal 0059 for ZwImpersonateAnonymousToken (NtImpersonateAnonymousToken)
7c90dadb: Syscall ordinal 005a for ZwImpersonateClientOfPort (NtImpersonateClientOfPort)
7c90daf0: Syscall ordinal 005b for ZwImpersonateThread (NtImpersonateThread)
7c90db05: Syscall ordinal 005c for ZwInitializeRegistry (NtInitializeRegistry)
7c90db1a: Syscall ordinal 005d for ZwInitiatePowerAction (NtInitiatePowerAction)
7c90db2f: Syscall ordinal 005e for ZwIsProcessInJob (NtIsProcessInJob)
7c90db44: Syscall ordinal 005f for ZwIsSystemResumeAutomatic (NtIsSystemResumeAutomatic)
7c90db59: Syscall ordinal 0060 for ZwListenPort (NtListenPort)
7c90db6e: Syscall ordinal 0061 for ZwLoadDriver (NtLoadDriver)
7c90db83: Syscall ordinal 0062 for ZwLoadKey (NtLoadKey)
7c90db98: Syscall ordinal 0063 for ZwLoadKey2 (NtLoadKey2)
7c90dbad: Syscall ordinal 0064 for ZwLockFile (NtLockFile)
7c90dbc2: Syscall ordinal 0065 for ZwLockProductActivationKeys (NtLockProductActivationKeys)
7c90dbd7: Syscall ordinal 0066 for ZwLockRegistryKey (NtLockRegistryKey)
7c90dbec: Syscall ordinal 0067 for ZwLockVirtualMemory (NtLockVirtualMemory)
7c90dc01: Syscall ordinal 0068 for ZwMakePermanentObject (NtMakePermanentObject)
7c90dc16: Syscall ordinal 0069 for ZwMakeTemporaryObject (NtMakeTemporaryObject)
7c90dc2b: Syscall ordinal 006a for ZwMapUserPhysicalPages (NtMapUserPhysicalPages)
7c90dc40: Syscall ordinal 006b for ZwMapUserPhysicalPagesScatter (NtMapUserPhysicalPagesScatter)
7c90dc55: Syscall ordinal 006c for ZwMapViewOfSection (NtMapViewOfSection)
7c90dc6a: Syscall ordinal 006d for ZwModifyBootEntry (NtModifyBootEntry)
7c90dc7f: Syscall ordinal 006e for ZwNotifyChangeDirectoryFile (NtNotifyChangeDirectoryFile)
7c90dc94: Syscall ordinal 006f for ZwNotifyChangeKey (NtNotifyChangeKey)
7c90dca9: Syscall ordinal 0070 for ZwNotifyChangeMultipleKeys (NtNotifyChangeMultipleKeys)
7c90dcbe: Syscall ordinal 0071 for ZwOpenDirectoryObject (NtOpenDirectoryObject)
7c90dcd3: Syscall ordinal 0072 for ZwOpenEvent (NtOpenEvent)
7c90dce8: Syscall ordinal 0073 for ZwOpenEventPair (NtOpenEventPair)
7c90dcfd: Syscall ordinal 0074 for ZwOpenFile (NtOpenFile)
7c90dd12: Syscall ordinal 0075 for ZwOpenIoCompletion (NtOpenIoCompletion)
7c90dd27: Syscall ordinal 0076 for ZwOpenJobObject (NtOpenJobObject)
7c90dd3c: Syscall ordinal 0077 for ZwOpenKey (NtOpenKey)
7c90dd51: Syscall ordinal 0078 for ZwOpenMutant (NtOpenMutant)
7c90dd66: Syscall ordinal 0079 for ZwOpenObjectAuditAlarm (NtOpenObjectAuditAlarm)
7c90dd7b: Syscall ordinal 007a for ZwOpenProcess (NtOpenProcess)
7c90dd90: Syscall ordinal 007b for ZwOpenProcessToken (NtOpenProcessToken)
7c90dda5: Syscall ordinal 007c for ZwOpenProcessTokenEx (NtOpenProcessTokenEx)
7c90ddba: Syscall ordinal 007d for ZwOpenSection (NtOpenSection)
7c90ddcf: Syscall ordinal 007e for ZwOpenSemaphore (NtOpenSemaphore)
7c90dde4: Syscall ordinal 007f for ZwOpenSymbolicLinkObject (NtOpenSymbolicLinkObject)
7c90ddf9: Syscall ordinal 0080 for ZwOpenThread (NtOpenThread)
7c90de0e: Syscall ordinal 0081 for ZwOpenThreadToken (NtOpenThreadToken)
7c90de23: Syscall ordinal 0082 for ZwOpenThreadTokenEx (NtOpenThreadTokenEx)
7c90de38: Syscall ordinal 0083 for ZwOpenTimer (NtOpenTimer)
7c90de4d: Syscall ordinal 0084 for ZwPlugPlayControl (NtPlugPlayControl)
7c90de62: Syscall ordinal 0085 for ZwPowerInformation (NtPowerInformation)
7c90de77: Syscall ordinal 0086 for ZwPrivilegeCheck (NtPrivilegeCheck)
7c90de8c: Syscall ordinal 0087 for ZwPrivilegeObjectAuditAlarm (NtPrivilegeObjectAuditAlarm)
7c90dea1: Syscall ordinal 0088 for ZwPrivilegedServiceAuditAlarm (NtPrivilegedServiceAuditAlarm)
7c90deb6: Syscall ordinal 0089 for ZwProtectVirtualMemory (NtProtectVirtualMemory)
7c90decb: Syscall ordinal 008a for ZwPulseEvent (NtPulseEvent)
7c90dee0: Syscall ordinal 008b for ZwQueryAttributesFile (NtQueryAttributesFile)
7c90def5: Syscall ordinal 008c for ZwQueryBootEntryOrder (NtQueryBootEntryOrder)
7c90df0a: Syscall ordinal 008d for ZwQueryBootOptions (NtQueryBootOptions)
7c90df1f: Syscall ordinal 008e for ZwQueryDebugFilterState (NtQueryDebugFilterState)
7c90df34: Syscall ordinal 008f for ZwQueryDefaultLocale (NtQueryDefaultLocale)
7c90df49: Syscall ordinal 0090 for ZwQueryDefaultUILanguage (NtQueryDefaultUILanguage)
7c90df5e: Syscall ordinal 0091 for ZwQueryDirectoryFile (NtQueryDirectoryFile)
7c90df73: Syscall ordinal 0092 for ZwQueryDirectoryObject (NtQueryDirectoryObject)
7c90df88: Syscall ordinal 0093 for ZwQueryEaFile (NtQueryEaFile)
7c90df9d: Syscall ordinal 0094 for ZwQueryEvent (NtQueryEvent)
7c90dfb2: Syscall ordinal 0095 for ZwQueryFullAttributesFile (NtQueryFullAttributesFile)
7c90dfc7: Syscall ordinal 0096 for ZwQueryInformationAtom (NtQueryInformationAtom)
7c90dfdc: Syscall ordinal 0097 for ZwQueryInformationFile (NtQueryInformationFile)
7c90dff1: Syscall ordinal 0098 for ZwQueryInformationJobObject (NtQueryInformationJobObject)
7c90e006: Syscall ordinal 0099 for ZwQueryInformationPort (NtQueryInformationPort)
7c90e01b: Syscall ordinal 009a for ZwQueryInformationProcess (NtQueryInformationProcess)
7c90e030: Syscall ordinal 009b for ZwQueryInformationThread (NtQueryInformationThread)
7c90e045: Syscall ordinal 009c for ZwQueryInformationToken (NtQueryInformationToken)
7c90e05a: Syscall ordinal 009d for ZwQueryInstallUILanguage (NtQueryInstallUILanguage)
7c90e06f: Syscall ordinal 009e for ZwQueryIntervalProfile (NtQueryIntervalProfile)
7c90e084: Syscall ordinal 009f for ZwQueryIoCompletion (NtQueryIoCompletion)
7c90e099: Syscall ordinal 00a0 for ZwQueryKey (NtQueryKey)
7c90e0ae: Syscall ordinal 00a1 for ZwQueryMultipleValueKey (NtQueryMultipleValueKey)
7c90e0c3: Syscall ordinal 00a2 for ZwQueryMutant (NtQueryMutant)
7c90e0d8: Syscall ordinal 00a3 for ZwQueryObject (NtQueryObject)
7c90e0ed: Syscall ordinal 00a4 for ZwQueryOpenSubKeys (NtQueryOpenSubKeys)
7c90e102: Syscall ordinal 00a5 for ZwQueryPerformanceCounter (NtQueryPerformanceCounter)
7c90e117: Syscall ordinal 00a6 for ZwQueryQuotaInformationFile (NtQueryQuotaInformationFile)
7c90e12c: Syscall ordinal 00a7 for ZwQuerySection (NtQuerySection)
7c90e141: Syscall ordinal 00a8 for ZwQuerySecurityObject (NtQuerySecurityObject)
7c90e156: Syscall ordinal 00a9 for ZwQuerySemaphore (NtQuerySemaphore)
7c90e16b: Syscall ordinal 00aa for ZwQuerySymbolicLinkObject (NtQuerySymbolicLinkObject)
7c90e180: Syscall ordinal 00ab for ZwQuerySystemEnvironmentValue (NtQuerySystemEnvironmentValue)
7c90e195: Syscall ordinal 00ac for ZwQuerySystemEnvironmentValueEx (NtQuerySystemEnvironmentValueEx)
7c90e1aa: Syscall ordinal 00ad for ZwQuerySystemInformation (NtQuerySystemInformation
RtlGetNativeSystemInformation)
7c90e1bf: Syscall ordinal 00ae for ZwQuerySystemTime (NtQuerySystemTime)
7c90e1d4: Syscall ordinal 00af for ZwQueryTimer (NtQueryTimer)
7c90e1e9: Syscall ordinal 00b0 for ZwQueryTimerResolution (NtQueryTimerResolution)
7c90e1fe: Syscall ordinal 00b1 for ZwQueryValueKey (NtQueryValueKey)
7c90e213: Syscall ordinal 00b2 for ZwQueryVirtualMemory (NtQueryVirtualMemory)
7c90e228: Syscall ordinal 00b3 for ZwQueryVolumeInformationFile (NtQueryVolumeInformationFile)
7c90e23d: Syscall ordinal 00b4 for ZwQueueApcThread (NtQueueApcThread)
7c90e252: Syscall ordinal 00b5 for ZwRaiseException (NtRaiseException)
7c90e267: Syscall ordinal 00b6 for ZwRaiseHardError (NtRaiseHardError)
7c90e27c: Syscall ordinal 00b7 for ZwReadFile (NtReadFile)
7c90e291: Syscall ordinal 00b8 for ZwReadFileScatter (NtReadFileScatter)
7c90e2a6: Syscall ordinal 00b9 for ZwReadRequestData (NtReadRequestData)
7c90e2bb: Syscall ordinal 00ba for ZwReadVirtualMemory (NtReadVirtualMemory)
7c90e2d0: Syscall ordinal 00bb for ZwRegisterThreadTerminatePort (NtRegisterThreadTerminatePort)
7c90e2e5: Syscall ordinal 00bc for ZwReleaseMutant (NtReleaseMutant)
7c90e2fa: Syscall ordinal 00bd for ZwReleaseSemaphore (NtReleaseSemaphore)
7c90e30f: Syscall ordinal 00be for ZwRemoveIoCompletion (NtRemoveIoCompletion)
7c90e324: Syscall ordinal 00bf for ZwRemoveProcessDebug (NtRemoveProcessDebug)
7c90e339: Syscall ordinal 00c0 for ZwRenameKey (NtRenameKey)
7c90e34e: Syscall ordinal 00c1 for ZwReplaceKey (NtReplaceKey)
7c90e363: Syscall ordinal 00c2 for ZwReplyPort (NtReplyPort)
7c90e378: Syscall ordinal 00c3 for ZwReplyWaitReceivePort (NtReplyWaitReceivePort)
7c90e38d: Syscall ordinal 00c4 for ZwReplyWaitReceivePortEx (NtReplyWaitReceivePortEx)
7c90e3a2: Syscall ordinal 00c5 for ZwReplyWaitReplyPort (NtReplyWaitReplyPort)
7c90e3b7: Syscall ordinal 00c6 for ZwRequestDeviceWakeup (NtRequestDeviceWakeup)
7c90e3cc: Syscall ordinal 00c7 for ZwRequestPort (NtRequestPort)
7c90e3e1: Syscall ordinal 00c8 for ZwRequestWaitReplyPort (NtRequestWaitReplyPort)
7c90e3f6: Syscall ordinal 00c9 for ZwRequestWakeupLatency (NtRequestWakeupLatency)
7c90e40b: Syscall ordinal 00ca for ZwResetEvent (NtResetEvent)
7c90e420: Syscall ordinal 00cb for ZwResetWriteWatch (NtResetWriteWatch)
7c90e435: Syscall ordinal 00cc for ZwRestoreKey (NtRestoreKey)
7c90e44a: Syscall ordinal 00cd for ZwResumeProcess (NtResumeProcess)
7c90e45f: Syscall ordinal 00ce for ZwResumeThread (NtResumeThread)
7c90e474: Syscall ordinal 00cf for ZwSaveKey (NtSaveKey)
7c90e489: Syscall ordinal 00d0 for ZwSaveKeyEx (NtSaveKeyEx)
7c90e49e: Syscall ordinal 00d1 for ZwSaveMergedKeys (NtSaveMergedKeys)
7c90e4b3: Syscall ordinal 00d2 for ZwSecureConnectPort (NtSecureConnectPort)
7c90e4c8: Syscall ordinal 00d3 for ZwSetBootEntryOrder (NtSetBootEntryOrder)
7c90e4dd: Syscall ordinal 00d4 for ZwSetBootOptions (NtSetBootOptions)
7c90e4f2: Syscall ordinal 00d5 for ZwSetContextThread (NtSetContextThread)
7c90e507: Syscall ordinal 00d6 for ZwSetDebugFilterState (NtSetDebugFilterState)
7c90e51c: Syscall ordinal 00d7 for ZwSetDefaultHardErrorPort (NtSetDefaultHardErrorPort)
7c90e531: Syscall ordinal 00d8 for ZwSetDefaultLocale (NtSetDefaultLocale)
7c90e546: Syscall ordinal 00d9 for ZwSetDefaultUILanguage (NtSetDefaultUILanguage)
7c90e55b: Syscall ordinal 00da for ZwSetEaFile (NtSetEaFile)
7c90e570: Syscall ordinal 00db for ZwSetEvent (NtSetEvent)
7c90e585: Syscall ordinal 00dc for ZwSetEventBoostPriority (NtSetEventBoostPriority)
7c90e59a: Syscall ordinal 00dd for ZwSetHighEventPair (NtSetHighEventPair)
7c90e5af: Syscall ordinal 00de for ZwSetHighWaitLowEventPair (NtSetHighWaitLowEventPair)
7c90e5c4: Syscall ordinal 00df for ZwSetInformationDebugObject (NtSetInformationDebugObject)
7c90e5d9: Syscall ordinal 00e0 for ZwSetInformationFile (NtSetInformationFile)
7c90e5ee: Syscall ordinal 00e1 for ZwSetInformationJobObject (NtSetInformationJobObject)
7c90e603: Syscall ordinal 00e2 for ZwSetInformationKey (NtSetInformationKey)
7c90e618: Syscall ordinal 00e3 for ZwSetInformationObject (NtSetInformationObject)
7c90e62d: Syscall ordinal 00e4 for ZwSetInformationProcess (NtSetInformationProcess)
7c90e642: Syscall ordinal 00e5 for ZwSetInformationThread (NtSetInformationThread)
7c90e657: Syscall ordinal 00e6 for ZwSetInformationToken (NtSetInformationToken)
7c90e66c: Syscall ordinal 00e7 for ZwSetIntervalProfile (NtSetIntervalProfile)
7c90e681: Syscall ordinal 00e8 for ZwSetIoCompletion (NtSetIoCompletion)
7c90e696: Syscall ordinal 00e9 for ZwSetLdtEntries (NtSetLdtEntries)
7c90e6ab: Syscall ordinal 00ea for ZwSetLowEventPair (NtSetLowEventPair)
7c90e6c0: Syscall ordinal 00eb for ZwSetLowWaitHighEventPair (NtSetLowWaitHighEventPair)
7c90e6d5: Syscall ordinal 00ec for ZwSetQuotaInformationFile (NtSetQuotaInformationFile)
7c90e6ea: Syscall ordinal 00ed for ZwSetSecurityObject (NtSetSecurityObject)
7c90e6ff: Syscall ordinal 00ee for ZwSetSystemEnvironmentValue (NtSetSystemEnvironmentValue)
7c90e714: Syscall ordinal 00ef for ZwSetSystemEnvironmentValueEx (NtSetSystemEnvironmentValueEx)
7c90e729: Syscall ordinal 00f0 for ZwSetSystemInformation (NtSetSystemInformation)
7c90e73e: Syscall ordinal 00f1 for ZwSetSystemPowerState (NtSetSystemPowerState)
7c90e753: Syscall ordinal 00f2 for ZwSetSystemTime (NtSetSystemTime)
7c90e768: Syscall ordinal 00f3 for ZwSetThreadExecutionState (NtSetThreadExecutionState)
7c90e77d: Syscall ordinal 00f4 for ZwSetTimer (NtSetTimer)
7c90e792: Syscall ordinal 00f5 for ZwSetTimerResolution (NtSetTimerResolution)
7c90e7a7: Syscall ordinal 00f6 for ZwSetUuidSeed (NtSetUuidSeed)
7c90e7bc: Syscall ordinal 00f7 for ZwSetValueKey (NtSetValueKey)
7c90e7d1: Syscall ordinal 00f8 for ZwSetVolumeInformationFile (NtSetVolumeInformationFile)
7c90e7e6: Syscall ordinal 00f9 for ZwShutdownSystem (NtShutdownSystem)
7c90e7fb: Syscall ordinal 00fa for ZwSignalAndWaitForSingleObject (NtSignalAndWaitForSingleObject)
7c90e810: Syscall ordinal 00fb for ZwStartProfile (NtStartProfile)
7c90e825: Syscall ordinal 00fc for ZwStopProfile (NtStopProfile)
7c90e83a: Syscall ordinal 00fd for ZwSuspendProcess (NtSuspendProcess)
7c90e84f: Syscall ordinal 00fe for ZwSuspendThread (NtSuspendThread)
7c90e864: Syscall ordinal 00ff for ZwSystemDebugControl (NtSystemDebugControl)

Update: As somebody pointed out in the comments, there's a really good compilation of system call ordinals up at Metasploit's site.

Tuesday, March 04, 2008

Recon 2008

So, it seems that after a year off Recon is coming back in 2008. I attended last time it was held and was one of the best conferences I've been to.

Sunday, March 02, 2008

Old interviews with members of 29A

The guys at Hispasec managed to dig up some old interviews with members GriYo and MrSandman of the legendary group 29A that recently announced was closing shop. Definitely worth a read if you can handle spanish.

Tuesday, February 19, 2008

badass debugger + badass toy = geek pr0n

Today I finally got working a hacked-together minimal version of the iPhone debugger client for BinNavi. It's heavily based on Patrick Walton's (with HD's updates) weasel debugger. Once tied to BinNavi debug client framework the whole client-server interaction is trivial.

It feels just right, the best looking debugger together with the slickest device.. recipe for fun.. ;-)



The test application is telnet on the iPhone. On the iPhone's screen is the debug output from BinNavi's debug client. telnet is launched from an ssh session in OSX, where BinNavi is running.



For anybody trying to link Mach's debugging interface with a C++ iPhone application, remember the extern "C" when defining boolean_t exc_server(mach_msg_header_t *in, mach_msg_header_t *out); (which is not defined in the header files, as pointed in weasel's source code). Otherwise you'll get a nasty "Undefined symbols" message when linking.

extern "C" is also needed for catch_exception_raise(...) so exc_server can call it to handle exceptions. Documented here.
(I've used the standard iPhone toolchain on Debian, this is running on the firmware 1.1.3)

Sunday, November 25, 2007

pefile 1.2.8

And yet another one. pefile 1.2.8 comes with the usual few bugfixes and a slew of enhancements. Some of them are:
  • One can now "relocate" the image by invoking relocate_image(ImageBase) with a new ImageBase the PE file's relocations will be applied to produce the relocated image.

  • Section entropy is computed faster (thanks to Gergely)

  • MD5, SHA-1, SHA-256, SHA-512 hashes are calculated on a per-section basis (thanks Jim Clausing for the suggestion)

  • Improved (rather fixed) handling of Unicode strings when parsing the resources information

For more details and downloads head to pefile's project page.

Wednesday, November 21, 2007

Packers, Time and Google Groups

The other day I was talking with a friend and the discussion went into when certain anti-disassembly, anti-debug, etc. techniques might have appeared. That's bound to be difficult because tricks are usually simultaneously discovered by different people.

So I though, a trick will usually be regarded as "common" once it gets implemented in some packer, as those try to make analysis difficult and will attempt to embedded whichever tricks are good/popular within the underground at the time in order to make the reverse engineering process as cumbersome as possible. Therefore if I could somehow place packers in time I'd have a starting point...

That led me to remember about Google Groups. It's possible to make queries restricted to date ranges and the archives go back to 1981. I quickly put together a script to scan with a one-month window through 1981 to 2007 for a set of popular packers.

The most painful part of the whole process was to fool Google... they sure do not like robots... whenever they get a bunch of very simply automated queries they'll server back a "403 Forbidden" telling queries look like coming from a virus or spyware app...
But my script is good, it's no evil spyware... so I got into the mood of working my way around the checks. I needed to do quite some queries (> 10K) so I better make it believe I'm not a robot. Besides finding the right timing for the queries (too often will make Google sad) I had to distribute the search over a few hosts, randomize headers and User-Agents and the query itself (just throw in some randomized, "orthogonal" (nothing to do with your query) search terms). After that the script was good to go...

So, after mining the news groups for popular packer names ( the search string was, most of the time, " exe" plus the "randomized" terms ) I got a cute small data set to throw into Mathematica...










The results will have some inaccuracies, as it's possible some of the terms appeared in some news post not related to the packers. Yet I think they look plausible. When the volume of hits is high enough or constant over time it feels like it would indicate the approximate release date of the packer in question, or at least the first public discussion about it which, I would tend to think, will not necessarily be too far apart.
If someone can either corroborate or refute the data I'll be glad to hear.

I also did some test overlaying virus release times in order to try to spot correlations between big outbreaks and news-posts about packers, but I couldn't see anything particularly significant.

Tuesday, September 18, 2007

Hex-Rays unleashed

Hex-Rays, Ilfak Guilfanov's decompiler, has been unleashed. I have had the chance of playing a bit with the beta and it is really impressive, to say the least. This will save so many hours to reverse engineers...

Sunday, September 09, 2007

Reverse engineering a compiler-produced artifact

In our training, Pedram and I deal with some very simple compiler optimizations or artifacts. Although they represent the same semantics that the programmer defined in the original source code, those optimizations are sometimes cumbersome to convert back to a meaningful high-level representation.

The other day I was just studying a piece of code and bumped into a relatively common pattern. The code I was looking at was supposed to represent a division of a function's argument by a constant. But in the disassembled code I was studying I could only see a multiplication. This can be slightly confusing unless one has seen a bit more assembly than what is healthy and remembers some of the compiler-produced fun that goes on...

A couple of things to remember:
  • Compilers love to work with multiples of 2. The processor can can just shift registers left and right (shifting is incredibly fast, that is moving the contents of a register left or right padding with o or 1 as appropriate). Shifting to the left for multiplication by 2 and towards the right for division by 2 (this is akin to having a number in base 10 and multiplying by 10 by adding zeros to the right and dividing by by removing the rightmost digit).
  • Compilers hate to use the division instruction. The division takes a lot of steps, or cycles, for the CPU to complete. Hence they will avoid to use it at all cost.

The code looked like this:
(irrelevant interleaved code left out)

mov ecx, [esp+4+arg_4]
mov eax, 66666667h
imul ecx
sar edx, 3


  • In the snippet we can see function argument being multiplied by 0x66666667, and the result being stored as a 64 bit value in EDX:EAX (topmost 32 bits in EDX, the lower 32 in EAX)
  • Then the top 32 bits are shifted ("arithmetically") to the right. That is, divided by 2 thrice, same as 2^3 = 8. Effectively dividing the value by 8.
  • But the division is applied only to the top 32 bits, ignoring the lower 32. That could be understood to also mean that, by taking the topmost 32 bits and ignoring the bottom ones, the result of the multiplication is implicitly being divided by 2^32. (That's only guessed by the subsequent usage of the value just obtained, there's never again a reference to the lower 32bits, so I assume that they are discarded)


What do we have so far?

[ (Value * 0x66666667) / 2^32 ] / 2^3 ]

But, what's that 0x66666667? why to multiply by something so large and then divide?
The reason is that such computation allows the processor to keep most of the precision of the division it is trying to perform, still obtaining an integer in the end but without having to resort to using floating point arithmetic (which is far slower)

Let's do an example in base 10. Imagine that you only can multiply and divide by 10 (shifting numbers left and right) and we want to divide a number by 30. By shifting we can only divide by 10, 100, 1000, etc

But we have that: Value/30 = value * 1/3 * 1/10

Given that, represented as an integer, 1/3 would produce 0 we can "scale" it by multiplying by a large constant that later, once we are done, we divide by to get the value we're after. Given that the easiest for us is to multiply/divide by 10, we can "scale" 1/3 and make it 100000/3 which approximately equals 33333, which is a nice integer value. We would want to make this value as large as it fits in our registers in order to be as precise as possible. The bigger it is the more precision it will retain for subsequent operations.

Value/30 = ( Value*33333 ) / 1000000

Hence, we now have a clue now of where that 0x66666667 value might be coming from. Given that the processor works in base 2. We can assume that it's going to prefer multiples of 2. Also, given that it will try to obtain the largest value that fits in a 32bit register, that gives us an idea of the range of the power-of-two in use. We can get there with a bit of trial and error (We want to obtain an integer as a result of dividing a power of two by 0x66666667).

2.0^33/0x66666667 = 4.9999999982537702 ~= 5

Therefore:

0x66666667 ~= 2^33/5

So, in the end we get to

( [ (Value * 2^33)/5] /2^32 ) / 2^3

And with some algebra it simplifies to:

Value / (5*2^2) = Value/20

Effectively dividing the value by 20, without actually using the division instruction. That's to the extent that compilers will go to avoid using the division instruction...

Reverse engineering is fun isn't it?

Update: Given that this is a relatively old and well known optimization strategy it's only natural that it had been discussed before. It was just brought to my attention that Ilfak had blogged about a similar optimization and this chapter (PDF) from Hacker's Delight provides more details.

Tuesday, August 28, 2007

Visualizations of the Portable Executable Format

I've always found that clear diagramming and laying out of complicated information makes it much more accessible and understandable.
When I started looking into the Portable Executable format I found it really helpful to lay out all the headers and structures I was trying to understand, to visualize how they relate to each other and the information they contain.
The resulting diagrams have been available under the corresponding section in OpenRCE for a some time already.

Now, given the feedback I received about some of those, I decided to put them up in an online store so people can get the real posters, high-resolution, updated and redesigned versions of those diagrams.

The Portable Executable Format poster has been updated to display the modified structures of the PE32+ format, while the Portable Executable Format. A File Walkthrough depicts the basic headers on top of a raw byte representation of an actual executable file.

Thursday, August 23, 2007

PyDbg hacks

Pedram just posted on his OpenRCE blog some awesome PyDBG hacks.

Friday, August 10, 2007

Black Hat Slides

Although originally Halvar Flake and I were supposed to present together in a quick turbo-talk at Black Hat in Las Vegas, he unfortunately couldn't make it to the conference for reasons that have been already discussed.

I ended up sticking mostly to the original plan for the talk and presented some Python tools to automate reverse engineering and analysis processes.

I've just put the slides up here.

pefile 1.2.6

It's finally here! Took longer than I expected because of all the enhancements and because I decided to move pefile to Google Code.

Besides access to the source code through their subversion server, they also have a really cute wiki.

I've added documentation and examples and it should make it easier for people to contribute ideas and improvements.

I introduced some of the new features of pefile in my turbo-talk in the last Black Hat in Las Vegas.

Besides some bugfixes, pefile-1.2.6 can now parse PEiD's signatures, it will report on the entropy of each section and will display more warnings for suspicious values found when parsing PE files. Just check the example dumps of Tiny PE and 0x90.exe

Information on how to use the PEiD signature matching can be found here. I posted a while ago on what can be done with the signature parsing.

Saturday, July 14, 2007

BlackHat Vegas is nearly here...

I'll be there, teaching with Pedram a couple of rounds (weekend and week) of our training, Reverse Engineering on Windows: Application in Malicious Code Analysis. And then ranting together with Halvar in a turbo talk, 4 x 5

Pedram and myself "live on stage"


For the people more into cutting edge vulnerability research, Halvar will also be doing his Analyzing Software for Security Vulnerabilities. Feel free to grab any of us during the conference if you have any questions regarding BinDiff, BinNavi or VxClass.

And now that I am in the mood of advertising things, be sure to check OpenRCE's event calendar, you can even subscribe to the iCal feed. I try to keep it up to date with whatever events fall into my ears. If anyone knows of more, please let me know.

Thursday, June 14, 2007

Safari 3.0.1 for Windows

Apple released today an update for the recently unleashed Safari for Windows attempting to fix some of the problems promptly uncovered after the inital release.

I wanted to take a look at all the changes in the release. After comparing the hashes of all executable modules the following were identical to the ones included in Safari 3.0.0:
  • coregraphics.dll, icudt36.dll, icuin36.dll, icuuc36.dll, libtidy.dll, libxml2.dll, libxslt.dll, javaplugin.jar, pthreadvc2.dll, sqlite3.dll, zlib1.dll

Of all the remaining, whose hashes were different, the following proved to be structurally identical after running them through BinDiff:
  • safariresources.dll, cfnetwork.dll, safaritheme.dll, pubsubdll.dll, npjavaplugin.dll, corefoundation.dll

So that leaves us with the stuff to focus on:
  • safari.exe and webkit.exe

The dependencies between this modules are show in the following graph (green=identical hash, black=hash changed but structurally identical, red=the meat)



Within those two modules, BinDiff finds a handful of functions changed, what could possibly have been fixed... ? ;)

BinNavi: Simplifying code II. The implementation

Following up the ideas presented on a previous post, this one will discuss their implementation.

We wanted to write some code that would help us understand the meaning of certain operations encoded in assembly instructions. We wanted to do that by going through the instructions and building extended expressions representing the relations between the input and output values of a basic block.

In order to implement the desired functionality, we will write some code to replace parts of the operand trees with existing, known values, from the already analyzed code.
  • The code will iterate through the operand tree until it finds leafs (labeled as ’l’)
  • The leafs will then be substituted if their contents are known
  • The new, augmented, operand tree will be returned

The main part of this simple operand expression "builder" is to parse instructions and keep track of the values of the operands for the current instruction. If any values can be augmented by including the operations performed in previous instructions, those will be replaced by the result of such operations.
  • The function will take a dictionary (aka associative array) instance that will map the registers and memory addresses to their known contents
  • It will parse each instruction and update the dictionary according to the semantics of the opcode which in this example won't be totally accurate but will suffice to illustrate the process
  • It will return an updated dictionary with the results of tracking the values

This first function will retrieve an operand tree and return it as a nested list.
(The code presented in this post makes use of BinNavi's Python scripting to access operands, instructions, etc)


# Retrieve an operand as nested lists
#
def get_optree(op, parent=None):
    if not parent:
        return get_optree(op, op.get_roots()[0])[0]
    tree = []
    children = op.get_children(parent)
    for child in children:
        subtree = get_optree(op, child)
        if subtree:
            tree.append( [str(child), subtree] )
        else:
            tree.append( [’l’, str(child)] )
    return tree



And the result of running it on the following instructions will be:

004A4703: lea b4 ecx,b4 ss [ebp+4294967240]
004A4706: push b4 26
004A4708: sub b4 eax,b4 ecx
004A470A: pop b4 ecx
004A470B: add b4 eax,b4 13

[[’l’, ’ecx’],
    [’ss’, [[’[’, [
    [’+’, [[’l’, ’ebp’], [’l’, ’4294967240’]]]]]]]]
[[’l’, ’26’]]
[[’l’, ’eax’], [’l’, ’ecx’]]
[[’l’, ’ecx’]]
[[’l’, ’eax’], [’l’, ’13’]]



The following function is in charge of substituting any values in the tree for which their content is known. For example, if ecx is used as a source operand but in a previous instruction is was assigned a value of 10, we would substitute ecx in the tree with 10.


# Substitute the leafs in the operand tree
# with the last values obtained during the
# analysis
#
def substitute_leafs(tree, operand_trees):
    if not isinstance(tree, list):
        return tree
    if isinstance(tree[0], str) and tree[0]==’l’:
        return operand_trees.get(str(tree), tree)
    else:
        for idx, elm in enumerate(tree):
            tree[idx] = substitute_leafs(elm, operand_trees)
    return tree


The next function will be responsible for parsing the semantics of the instructions (in a merely illustrative way, it's far from implementing strictly the semantics of the Intel instructions used here). Instructions responsible for basic arithmetic and assignment operations will be processed and their results stored in the operand tree that we are processing.


# Parse instructions

def parse_instruction(insn, stack, operand_trees=dict()):
    # Process the MOV instruction
    if insn.mnem == 'mov':
        # Get the operands
        dst, src = map(get_optree, insn.operands)
        # Perform substitutions for any known values
        src = substitute_leafs(src, operand_trees)
        # Assing the source operand to the destination
        operand_trees[str(dst)] = src
    elif insn.mnem == 'add':
        dst, src = map(get_optree, insn.operands)
        dst_expr = operand_trees.get(str(dst), dst)
        src = substitute_leafs(src, operand_trees)
        src_expr = operand_trees.get(str(src), src)
        operand_trees[str(dst)] = ['+', [dst_expr, src_expr]]
    elif insn.mnem == 'sub':
        dst, src = map(get_optree, insn.operands)
        dst_expr = operand_trees.get(str(dst), dst)
        src = substitute_leafs(src, operand_trees)
        src_expr = operand_trees.get(str(src), src)
        operand_trees[str(dst)] = ['+', [dst_expr, ['-', [src_expr]]]]
    elif insn.mnem == 'lea':
        dst, src = map(get_optree, insn.operands)
        src = substitute_leafs(src, operand_trees)
        src_expr = operand_trees.get(str(src), src)
        operand_trees[str(dst)] = src[1][0][1][0]
    elif insn.mnem == 'push':
        dst, src = ['l', 'STACK_TOP'], get_optree(insn.operands[0])
        src = substitute_leafs(src, operand_trees)
        src_expr = operand_trees.get(str(src), src)
        stack.append(src)
    elif insn.mnem == 'pop':
        dst, src = get_optree(insn.operands[0]), ['l', 'STACK_TOP']
        src = stack.pop()
        operand_trees[str(dst)] = src
    elif insn.mnem == 'cdq':
        pass
    elif insn.mnem == 'idiv':
        src = get_optree(insn.operands[0])
        # dst is always eax
        dst = ['l', 'eax']
        src = substitute_leafs(src, operand_trees)
        src_expr = operand_trees.get(str(src), src)
        orig_src = operand_trees.get(str(dst), dst)
        operand_trees[str(dst)] = ['*',
            [orig_src, ['INV', [src_expr]]] ]
        operand_trees[str(['l', 'edx'])] = ['%',
            [orig_src, ['mod', [src_expr]]] ]
    return operand_trees


After running the previous functions on a simple basic block, we will obtain operand trees representing the operations performed by the instructions on their operands.



In the end we can ask the value of a register and we will see, in a single extended expression, the value of the register as a result of all operations taking place in the basic block.


>>> operand_trees["['l', 'ecx']"]
['l', '(0x1A, 26)']

>>> operand_trees["['l', 'al']"]
['ss',
  [['[',
    [['+',
      [['l', 'ebp'],
      ['%',
        [['+',
          [['+',
            [['l', 'eax'],
            ['-', [['+',
              [['l', 'ebp'],
              ['l', 'lowercase_chars']]]]]]],
          ['l', '13']]],
        ['mod', [['l', '(0x1A, 26)']]]]],
      ['l', 'lowercase_chars']]]]]]]




We can also graphically represent the result of the operand composition in BinNavi.
The following function will traverse the operand tree and add the nodes to the graph instance provided.


# Convert nested lists into a graph object
# that can be visualized
#
def tree_to_graph(tree, g=Graph(), parent=None):
    if isinstance(tree[1], list):
        node_str = tree[0]
        node = g.add_node(str(node_str))
        if parent:
            g.add_edge(parent, node)
        for child in tree[1]:
            tree_to_graph(child, g, node)
    else:
        leaf = g.add_node(str(tree[1]))
        if parent:
            g.add_edge(parent, leaf)
    return g



And running it on one of the composed operand trees results in:


tree_to_graph(operand_trees["['l', 'al']"], Graph()).show()





As a last step we can represent the expression textually and add it to the node.


# Convert nested lists into a single expression as
# a string
#

def tree_to_expression(tree):
    root = tree[0]
    children = tree[1]
    if isinstance(children, list):
        parsed_children = [tree_to_expression(child) for child in children]
    else:
        return children
    if root == '*':
        return '(' + '*'.join(parsed_children) + ')'
    elif root == '+':
        return '(' + '+'.join(parsed_children) + ')'
    elif root == '-':
        return '(-' + parsed_children[0] + ')'
    elif root == '[':
        return '[' + ' '.join(parsed_children) + ']'
    elif root == 'INV':
        return 'INV('+parsed_children[0]+')'
    elif root == 'mod':
        return parsed_children[0]
    elif root == '%':
        return '(' + parsed_children[0]+'%'+parsed_children[1] + ')'
    elif root == 'l':
        return children
    elif root == 'ss':
        return parsed_children[0]



And running the following in BinNavi's Python interpreter will generate the expression and add it to the basic block as a comment in BinNavi's view.


fgv = Graphview.get_open_views()[0]
expr = tree_to_expression(operand_trees["['l', 'al']"])
fgv.set_node_comment(0x4a4703L, expr)





The resulting expression represents the ROT13 operation for lowercase characters. (The code belongs to the Mydoom.D worm)
ebp+lowercase_chars points to a string containing the alphabet. eax is the pointer to the character to encode/decode within the alphabet, and its position is calculated by subtracting the beginning address of the alphabet from eax. Then 13 is added to it and wrapped around by getting the value modulo 26 and added again to the beginning of the alphabet to obtain the final decoded/encoded character.
This expression is a nice and condensed form of expressing the functionality implemented in the basic block.

This post illustrates the versatility of a properly abstracted representation of the operands and instructions and the level of automation that can be achieved in a relatively simple manner with the help of the interactive Python scripting in BinNavi.

Monday, June 11, 2007

VxClass. Automated executable classification

Here at Sabre Security, we have been putting together a variety of technologies nurtured and developed over years of reverse engineering and malware analysis. All of it has taken form in VxClass, which is finally shaping up. We are quite proud and happy to see such a complex project (and one I've personally long dreamed about) actually working.



The first incarnation of VxClass is already able to automatically handle (unpack, analyze and classify) a wide range of Windows malware. The results are nearly addictive to look at. Accompanying this post are some screen-shots of the Web interface showing a listing of files and the automatically generated cluster of families.

VxClass will allow analysts or other tools to communicate with it and submit executable files. Those will be unpacked, analyzed and classified automatically according to their structural properties. The classification results as well as analysis databases can be retrieved through either an XMLRPC or a Web interface.



If you or your company would be interested on evaluating it or discussing if it might be an applicable technology for you, don't hesitate in dropping us a mail.

Also, I'm in the Bay Area for most of June and August (also in Black Hat in Las Vegas). So if you want to have me demo it or chat about it, drop me a line.

Saturday, June 09, 2007

pefile and packer detection

I've always wanted some tool that I could run over large collections of executable files and would tell me what's packed and what's not and, ideally, also the packer. PEiD has wonderful signature libraries but my ideal tool would be easier to integrate with other components and not restricted to Windows.
The guys at OffensiveComputing had put together some code to, by making use of PEiD signatures and pefile, recognize packers.

I've decided that it's time for pefile to have such functionality by default and I've reimplemented the signature parsing and matching. The next version of pefile should include this new code.
I've also found some pretty extensive signature libraries and here are some of results of the test runs in some files I've laying around.

Of the 48.025 files (all malware) that I scanned, in ~42% no packer could be found using the current signature database. In the remaining ~58% the tests found 227 different packers and compiler signatures.



A more extense listing of the most frequently found packers looks like:



Given that I've run pefile in several tens of thousands of pieces of malware with all kind of exotic PE format contortions, I've managed to find and fix a couple of obscure bugs. The forthcoming release will be even stronger when facing files that push the limits of the PE format well-formedness.

Thursday, May 31, 2007

Useful VB IDC script

Pierre just posted in Datarescue's forum about an IDC script for IDA contributed by Reginald Wong.
The script will run through Visual Basic executables and parse a good deal of object and form information. This will probably be interesting for anybody having to reverse engineer VB applications in IDA.

The script also points to some interesting resources:

Visual Basic Image Internal Structure Format by Alex Ionescu

Visual Basic Reversed - A decompiling approach by Andrea Geddon

Thursday, May 24, 2007

Google talk about reverse engeering to find security vulnerabilities

Great video of a Google talk by Alexander Sotirov on reverse engineering to find security vulnerabilities.

Sunday, May 20, 2007

ida2sql, exporting IDA's dissasemblies to SQL

Because BinNavi nowadays reads all the disassembly information from a SQL database, we needed some means of exporting the information to it. ida2sql is the result, it is a monster set of Python scripts I wrote (all nicely wrapped in a couple of files for easy installation) that will export the information from an IDB (only Intel, ARM and PPC so far. The latter two in experimental mode) into a MySQL database.
It's available for download from my site together with installation and usage instructions. It needs the IDAPython plug-in to run.

Any feedback is welcome.

I posted a while ago about the database schema. One can do pretty neat things when having the dissasembly in such form...