[Forensics-changes] [yara] 54/407: Implement import hashing.

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:28:09 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.3.0
in repository yara.

commit 6df98c0f57ac6de9939879ec1bd02c8122c93c56
Author: Wesley Shields <wxs at atarininja.org>
Date:   Tue Sep 23 22:22:33 2014 -0400

    Implement import hashing.
---
 libyara/modules/pe.c | 1904 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 1866 insertions(+), 38 deletions(-)

diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index f935bb4..86ae88b 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -20,6 +20,8 @@ limitations under the License.
 #include <yara/pe.h>
 #endif
 
+#include <ctype.h>
+#include <openssl/evp.h>
 #include <yara/modules.h>
 #include <yara/mem.h>
 #include <yara/strutils.h>
@@ -76,6 +78,27 @@ typedef int (*RESOURCE_CALLBACK_FUNC) ( \
      void* cb_data);
 
 
+/*
+ * Imports are stored in a linked list (IMPORT_LIST). Each node contains the
+ * name of the DLL and a pointer to another linked list (IMPORT_FUNC_LIST).
+ * The IMPORT_FUNC_LIST contains the names of each function imported from
+ * the corresponding DLL.
+ */
+typedef struct _IMPORT_LIST
+{
+  struct _IMPORT_LIST *next;
+  char *dll;
+  struct _IMPORT_FUNC_LIST *names;
+} IMPORT_LIST, *PIMPORT_LIST;
+
+
+typedef struct _IMPORT_FUNC_LIST
+{
+  struct _IMPORT_FUNC_LIST *next;
+  char *name;
+} IMPORT_FUNC_LIST, *PIMPORT_FUNC_LIST;
+
+
 typedef struct _PE
 {
   uint8_t* data;
@@ -84,9 +107,1584 @@ typedef struct _PE
   PIMAGE_NT_HEADERS32 header;
   YR_OBJECT* object;
   PRICH_DATA rich_data;
+  PIMPORT_LIST imports;
 
 } PE;
 
+/*
+ * These ordinals are taken from pefile. If a lookup fails attempt to return
+ * "ordN" and if that fails, return NULL. The caller is responsible for freeing
+ * the returned string.
+ */
+char *ord_lookup(
+    char *dll,
+    uint16_t ord)
+{
+  char *name = NULL;
+  if (strncasecmp(dll, "WS2_32.dll", 10) == 0 ||
+      strncasecmp(dll, "wsock32.dll", 11) == 0)
+  {
+    switch(ord) {
+      case 1:
+        asprintf(&name, "accept");
+        break;
+      case 2:
+        asprintf(&name, "bind");
+        break;
+      case 3:
+        asprintf(&name, "closesocket");
+        break;
+      case 4:
+        asprintf(&name, "connect");
+        break;
+      case 5:
+        asprintf(&name, "getpeername");
+        break;
+      case 6:
+        asprintf(&name, "getsockname");
+        break;
+      case 7:
+        asprintf(&name, "getsockopt");
+        break;
+      case 8:
+        asprintf(&name, "htonl");
+        break;
+      case 9:
+        asprintf(&name, "htons");
+        break;
+      case 10:
+        asprintf(&name, "ioctlsocket");
+        break;
+      case 11:
+        asprintf(&name, "inet_addr");
+        break;
+      case 12:
+        asprintf(&name, "inet_ntoa");
+        break;
+      case 13:
+        asprintf(&name, "listen");
+        break;
+      case 14:
+        asprintf(&name, "ntohl");
+        break;
+      case 15:
+        asprintf(&name, "ntohs");
+        break;
+      case 16:
+        asprintf(&name, "recv");
+        break;
+      case 17:
+        asprintf(&name, "recvfrom");
+        break;
+      case 18:
+        asprintf(&name, "select");
+        break;
+      case 19:
+        asprintf(&name, "send");
+        break;
+      case 20:
+        asprintf(&name, "sendto");
+        break;
+      case 21:
+        asprintf(&name, "setsockopt");
+        break;
+      case 22:
+        asprintf(&name, "shutdown");
+        break;
+      case 23:
+        asprintf(&name, "socket");
+        break;
+      case 24:
+        asprintf(&name, "GetAddrInfoW");
+        break;
+      case 25:
+        asprintf(&name, "GetNameInfoW");
+        break;
+      case 26:
+        asprintf(&name, "WSApSetPostRoutine");
+        break;
+      case 27:
+        asprintf(&name, "FreeAddrInfoW");
+        break;
+      case 28:
+        asprintf(&name, "WPUCompleteOverlappedRequest");
+        break;
+      case 29:
+        asprintf(&name, "WSAAccept");
+        break;
+      case 30:
+        asprintf(&name, "WSAAddressToStringA");
+        break;
+      case 31:
+        asprintf(&name, "WSAAddressToStringW");
+        break;
+      case 32:
+        asprintf(&name, "WSACloseEvent");
+        break;
+      case 33:
+        asprintf(&name, "WSAConnect");
+        break;
+      case 34:
+        asprintf(&name, "WSACreateEvent");
+        break;
+      case 35:
+        asprintf(&name, "WSADuplicateSocketA");
+        break;
+      case 36:
+        asprintf(&name, "WSADuplicateSocketW");
+        break;
+      case 37:
+        asprintf(&name, "WSAEnumNameSpaceProvidersA");
+        break;
+      case 38:
+        asprintf(&name, "WSAEnumNameSpaceProvidersW");
+        break;
+      case 39:
+        asprintf(&name, "WSAEnumNetworkEvents");
+        break;
+      case 40:
+        asprintf(&name, "WSAEnumProtocolsA");
+        break;
+      case 41:
+        asprintf(&name, "WSAEnumProtocolsW");
+        break;
+      case 42:
+        asprintf(&name, "WSAEventSelect");
+        break;
+      case 43:
+        asprintf(&name, "WSAGetOverlappedResult");
+        break;
+      case 44:
+        asprintf(&name, "WSAGetQOSByName");
+        break;
+      case 45:
+        asprintf(&name, "WSAGetServiceClassInfoA");
+        break;
+      case 46:
+        asprintf(&name, "WSAGetServiceClassInfoW");
+        break;
+      case 47:
+        asprintf(&name, "WSAGetServiceClassNameByClassIdA");
+        break;
+      case 48:
+        asprintf(&name, "WSAGetServiceClassNameByClassIdW");
+        break;
+      case 49:
+        asprintf(&name, "WSAHtonl");
+        break;
+      case 50:
+        asprintf(&name, "WSAHtons");
+        break;
+      case 51:
+        asprintf(&name, "gethostbyaddr");
+        break;
+      case 52:
+        asprintf(&name, "gethostbyname");
+        break;
+      case 53:
+        asprintf(&name, "getprotobyname");
+        break;
+      case 54:
+        asprintf(&name, "getprotobynumber");
+        break;
+      case 55:
+        asprintf(&name, "getservbyname");
+        break;
+      case 56:
+        asprintf(&name, "getservbyport");
+        break;
+      case 57:
+        asprintf(&name, "gethostname");
+        break;
+      case 58:
+        asprintf(&name, "WSAInstallServiceClassA");
+        break;
+      case 59:
+        asprintf(&name, "WSAInstallServiceClassW");
+        break;
+      case 60:
+        asprintf(&name, "WSAIoctl");
+        break;
+      case 61:
+        asprintf(&name, "WSAJoinLeaf");
+        break;
+      case 62:
+        asprintf(&name, "WSALookupServiceBeginA");
+        break;
+      case 63:
+        asprintf(&name, "WSALookupServiceBeginW");
+        break;
+      case 64:
+        asprintf(&name, "WSALookupServiceEnd");
+        break;
+      case 65:
+        asprintf(&name, "WSALookupServiceNextA");
+        break;
+      case 66:
+        asprintf(&name, "WSALookupServiceNextW");
+        break;
+      case 67:
+        asprintf(&name, "WSANSPIoctl");
+        break;
+      case 68:
+        asprintf(&name, "WSANtohl");
+        break;
+      case 69:
+        asprintf(&name, "WSANtohs");
+        break;
+      case 70:
+        asprintf(&name, "WSAProviderConfigChange");
+        break;
+      case 71:
+        asprintf(&name, "WSARecv");
+        break;
+      case 72:
+        asprintf(&name, "WSARecvDisconnect");
+        break;
+      case 73:
+        asprintf(&name, "WSARecvFrom");
+        break;
+      case 74:
+        asprintf(&name, "WSARemoveServiceClass");
+        break;
+      case 75:
+        asprintf(&name, "WSAResetEvent");
+        break;
+      case 76:
+        asprintf(&name, "WSASend");
+        break;
+      case 77:
+        asprintf(&name, "WSASendDisconnect");
+        break;
+      case 78:
+        asprintf(&name, "WSASendTo");
+        break;
+      case 79:
+        asprintf(&name, "WSASetEvent");
+        break;
+      case 80:
+        asprintf(&name, "WSASetServiceA");
+        break;
+      case 81:
+        asprintf(&name, "WSASetServiceW");
+        break;
+      case 82:
+        asprintf(&name, "WSASocketA");
+        break;
+      case 83:
+        asprintf(&name, "WSASocketW");
+        break;
+      case 84:
+        asprintf(&name, "WSAStringToAddressA");
+        break;
+      case 85:
+        asprintf(&name, "WSAStringToAddressW");
+        break;
+      case 86:
+        asprintf(&name, "WSAWaitForMultipleEvents");
+        break;
+      case 87:
+        asprintf(&name, "WSCDeinstallProvider");
+        break;
+      case 88:
+        asprintf(&name, "WSCEnableNSProvider");
+        break;
+      case 89:
+        asprintf(&name, "WSCEnumProtocols");
+        break;
+      case 90:
+        asprintf(&name, "WSCGetProviderPath");
+        break;
+      case 91:
+        asprintf(&name, "WSCInstallNameSpace");
+        break;
+      case 92:
+        asprintf(&name, "WSCInstallProvider");
+        break;
+      case 93:
+        asprintf(&name, "WSCUnInstallNameSpace");
+        break;
+      case 94:
+        asprintf(&name, "WSCUpdateProvider");
+        break;
+      case 95:
+        asprintf(&name, "WSCWriteNameSpaceOrder");
+        break;
+      case 96:
+        asprintf(&name, "WSCWriteProviderOrder");
+        break;
+      case 97:
+        asprintf(&name, "freeaddrinfo");
+        break;
+      case 98:
+        asprintf(&name, "getaddrinfo");
+        break;
+      case 99:
+        asprintf(&name, "getnameinfo");
+        break;
+      case 101:
+        asprintf(&name, "WSAAsyncSelect");
+        break;
+      case 102:
+        asprintf(&name, "WSAAsyncGetHostByAddr");
+        break;
+      case 103:
+        asprintf(&name, "WSAAsyncGetHostByName");
+        break;
+      case 104:
+        asprintf(&name, "WSAAsyncGetProtoByNumber");
+        break;
+      case 105:
+        asprintf(&name, "WSAAsyncGetProtoByName");
+        break;
+      case 106:
+        asprintf(&name, "WSAAsyncGetServByPort");
+        break;
+      case 107:
+        asprintf(&name, "WSAAsyncGetServByName");
+        break;
+      case 108:
+        asprintf(&name, "WSACancelAsyncRequest");
+        break;
+      case 109:
+        asprintf(&name, "WSASetBlockingHook");
+        break;
+      case 110:
+        asprintf(&name, "WSAUnhookBlockingHook");
+        break;
+      case 111:
+        asprintf(&name, "WSAGetLastError");
+        break;
+      case 112:
+        asprintf(&name, "WSASetLastError");
+        break;
+      case 113:
+        asprintf(&name, "WSACancelBlockingCall");
+        break;
+      case 114:
+        asprintf(&name, "WSAIsBlocking");
+        break;
+      case 115:
+        asprintf(&name, "WSAStartup");
+        break;
+      case 116:
+        asprintf(&name, "WSACleanup");
+        break;
+      case 151:
+        asprintf(&name, "__WSAFDIsSet");
+        break;
+      case 500:
+        asprintf(&name, "WEP");
+        break;
+      default:
+        break;
+    }
+  }
+  else if (strncasecmp(dll, "oleaut32.dll", 12) == 0)
+  {
+    switch (ord) {
+      case 2:
+        asprintf(&name, "SysAllocString");
+        break;
+      case 3:
+        asprintf(&name, "SysReAllocString");
+        break;
+      case 4:
+        asprintf(&name, "SysAllocStringLen");
+        break;
+      case 5:
+        asprintf(&name, "SysReAllocStringLen");
+        break;
+      case 6:
+        asprintf(&name, "SysFreeString");
+        break;
+      case 7:
+        asprintf(&name, "SysStringLen");
+        break;
+      case 8:
+        asprintf(&name, "VariantInit");
+        break;
+      case 9:
+        asprintf(&name, "VariantClear");
+        break;
+      case 10:
+        asprintf(&name, "VariantCopy");
+        break;
+      case 11:
+        asprintf(&name, "VariantCopyInd");
+        break;
+      case 12:
+        asprintf(&name, "VariantChangeType");
+        break;
+      case 13:
+        asprintf(&name, "VariantTimeToDosDateTime");
+        break;
+      case 14:
+        asprintf(&name, "DosDateTimeToVariantTime");
+        break;
+      case 15:
+        asprintf(&name, "SafeArrayCreate");
+        break;
+      case 16:
+        asprintf(&name, "SafeArrayDestroy");
+        break;
+      case 17:
+        asprintf(&name, "SafeArrayGetDim");
+        break;
+      case 18:
+        asprintf(&name, "SafeArrayGetElemsize");
+        break;
+      case 19:
+        asprintf(&name, "SafeArrayGetUBound");
+        break;
+      case 20:
+        asprintf(&name, "SafeArrayGetLBound");
+        break;
+      case 21:
+        asprintf(&name, "SafeArrayLock");
+        break;
+      case 22:
+        asprintf(&name, "SafeArrayUnlock");
+        break;
+      case 23:
+        asprintf(&name, "SafeArrayAccessData");
+        break;
+      case 24:
+        asprintf(&name, "SafeArrayUnaccessData");
+        break;
+      case 25:
+        asprintf(&name, "SafeArrayGetElement");
+        break;
+      case 26:
+        asprintf(&name, "SafeArrayPutElement");
+        break;
+      case 27:
+        asprintf(&name, "SafeArrayCopy");
+        break;
+      case 28:
+        asprintf(&name, "DispGetParam");
+        break;
+      case 29:
+        asprintf(&name, "DispGetIDsOfNames");
+        break;
+      case 30:
+        asprintf(&name, "DispInvoke");
+        break;
+      case 31:
+        asprintf(&name, "CreateDispTypeInfo");
+        break;
+      case 32:
+        asprintf(&name, "CreateStdDispatch");
+        break;
+      case 33:
+        asprintf(&name, "RegisterActiveObject");
+        break;
+      case 34:
+        asprintf(&name, "RevokeActiveObject");
+        break;
+      case 35:
+        asprintf(&name, "GetActiveObject");
+        break;
+      case 36:
+        asprintf(&name, "SafeArrayAllocDescriptor");
+        break;
+      case 37:
+        asprintf(&name, "SafeArrayAllocData");
+        break;
+      case 38:
+        asprintf(&name, "SafeArrayDestroyDescriptor");
+        break;
+      case 39:
+        asprintf(&name, "SafeArrayDestroyData");
+        break;
+      case 40:
+        asprintf(&name, "SafeArrayRedim");
+        break;
+      case 41:
+        asprintf(&name, "SafeArrayAllocDescriptorEx");
+        break;
+      case 42:
+        asprintf(&name, "SafeArrayCreateEx");
+        break;
+      case 43:
+        asprintf(&name, "SafeArrayCreateVectorEx");
+        break;
+      case 44:
+        asprintf(&name, "SafeArraySetRecordInfo");
+        break;
+      case 45:
+        asprintf(&name, "SafeArrayGetRecordInfo");
+        break;
+      case 46:
+        asprintf(&name, "VarParseNumFromStr");
+        break;
+      case 47:
+        asprintf(&name, "VarNumFromParseNum");
+        break;
+      case 48:
+        asprintf(&name, "VarI2FromUI1");
+        break;
+      case 49:
+        asprintf(&name, "VarI2FromI4");
+        break;
+      case 50:
+        asprintf(&name, "VarI2FromR4");
+        break;
+      case 51:
+        asprintf(&name, "VarI2FromR8");
+        break;
+      case 52:
+        asprintf(&name, "VarI2FromCy");
+        break;
+      case 53:
+        asprintf(&name, "VarI2FromDate");
+        break;
+      case 54:
+        asprintf(&name, "VarI2FromStr");
+        break;
+      case 55:
+        asprintf(&name, "VarI2FromDisp");
+        break;
+      case 56:
+        asprintf(&name, "VarI2FromBool");
+        break;
+      case 57:
+        asprintf(&name, "SafeArraySetIID");
+        break;
+      case 58:
+        asprintf(&name, "VarI4FromUI1");
+        break;
+      case 59:
+        asprintf(&name, "VarI4FromI2");
+        break;
+      case 60:
+        asprintf(&name, "VarI4FromR4");
+        break;
+      case 61:
+        asprintf(&name, "VarI4FromR8");
+        break;
+      case 62:
+        asprintf(&name, "VarI4FromCy");
+        break;
+      case 63:
+        asprintf(&name, "VarI4FromDate");
+        break;
+      case 64:
+        asprintf(&name, "VarI4FromStr");
+        break;
+      case 65:
+        asprintf(&name, "VarI4FromDisp");
+        break;
+      case 66:
+        asprintf(&name, "VarI4FromBool");
+        break;
+      case 67:
+        asprintf(&name, "SafeArrayGetIID");
+        break;
+      case 68:
+        asprintf(&name, "VarR4FromUI1");
+        break;
+      case 69:
+        asprintf(&name, "VarR4FromI2");
+        break;
+      case 70:
+        asprintf(&name, "VarR4FromI4");
+        break;
+      case 71:
+        asprintf(&name, "VarR4FromR8");
+        break;
+      case 72:
+        asprintf(&name, "VarR4FromCy");
+        break;
+      case 73:
+        asprintf(&name, "VarR4FromDate");
+        break;
+      case 74:
+        asprintf(&name, "VarR4FromStr");
+        break;
+      case 75:
+        asprintf(&name, "VarR4FromDisp");
+        break;
+      case 76:
+        asprintf(&name, "VarR4FromBool");
+        break;
+      case 77:
+        asprintf(&name, "SafeArrayGetVartype");
+        break;
+      case 78:
+        asprintf(&name, "VarR8FromUI1");
+        break;
+      case 79:
+        asprintf(&name, "VarR8FromI2");
+        break;
+      case 80:
+        asprintf(&name, "VarR8FromI4");
+        break;
+      case 81:
+        asprintf(&name, "VarR8FromR4");
+        break;
+      case 82:
+        asprintf(&name, "VarR8FromCy");
+        break;
+      case 83:
+        asprintf(&name, "VarR8FromDate");
+        break;
+      case 84:
+        asprintf(&name, "VarR8FromStr");
+        break;
+      case 85:
+        asprintf(&name, "VarR8FromDisp");
+        break;
+      case 86:
+        asprintf(&name, "VarR8FromBool");
+        break;
+      case 87:
+        asprintf(&name, "VarFormat");
+        break;
+      case 88:
+        asprintf(&name, "VarDateFromUI1");
+        break;
+      case 89:
+        asprintf(&name, "VarDateFromI2");
+        break;
+      case 90:
+        asprintf(&name, "VarDateFromI4");
+        break;
+      case 91:
+        asprintf(&name, "VarDateFromR4");
+        break;
+      case 92:
+        asprintf(&name, "VarDateFromR8");
+        break;
+      case 93:
+        asprintf(&name, "VarDateFromCy");
+        break;
+      case 94:
+        asprintf(&name, "VarDateFromStr");
+        break;
+      case 95:
+        asprintf(&name, "VarDateFromDisp");
+        break;
+      case 96:
+        asprintf(&name, "VarDateFromBool");
+        break;
+      case 97:
+        asprintf(&name, "VarFormatDateTime");
+        break;
+      case 98:
+        asprintf(&name, "VarCyFromUI1");
+        break;
+      case 99:
+        asprintf(&name, "VarCyFromI2");
+        break;
+      case 100:
+        asprintf(&name, "VarCyFromI4");
+        break;
+      case 101:
+        asprintf(&name, "VarCyFromR4");
+        break;
+      case 102:
+        asprintf(&name, "VarCyFromR8");
+        break;
+      case 103:
+        asprintf(&name, "VarCyFromDate");
+        break;
+      case 104:
+        asprintf(&name, "VarCyFromStr");
+        break;
+      case 105:
+        asprintf(&name, "VarCyFromDisp");
+        break;
+      case 106:
+        asprintf(&name, "VarCyFromBool");
+        break;
+      case 107:
+        asprintf(&name, "VarFormatNumber");
+        break;
+      case 108:
+        asprintf(&name, "VarBstrFromUI1");
+        break;
+      case 109:
+        asprintf(&name, "VarBstrFromI2");
+        break;
+      case 110:
+        asprintf(&name, "VarBstrFromI4");
+        break;
+      case 111:
+        asprintf(&name, "VarBstrFromR4");
+        break;
+      case 112:
+        asprintf(&name, "VarBstrFromR8");
+        break;
+      case 113:
+        asprintf(&name, "VarBstrFromCy");
+        break;
+      case 114:
+        asprintf(&name, "VarBstrFromDate");
+        break;
+      case 115:
+        asprintf(&name, "VarBstrFromDisp");
+        break;
+      case 116:
+        asprintf(&name, "VarBstrFromBool");
+        break;
+      case 117:
+        asprintf(&name, "VarFormatPercent");
+        break;
+      case 118:
+        asprintf(&name, "VarBoolFromUI1");
+        break;
+      case 119:
+        asprintf(&name, "VarBoolFromI2");
+        break;
+      case 120:
+        asprintf(&name, "VarBoolFromI4");
+        break;
+      case 121:
+        asprintf(&name, "VarBoolFromR4");
+        break;
+      case 122:
+        asprintf(&name, "VarBoolFromR8");
+        break;
+      case 123:
+        asprintf(&name, "VarBoolFromDate");
+        break;
+      case 124:
+        asprintf(&name, "VarBoolFromCy");
+        break;
+      case 125:
+        asprintf(&name, "VarBoolFromStr");
+        break;
+      case 126:
+        asprintf(&name, "VarBoolFromDisp");
+        break;
+      case 127:
+        asprintf(&name, "VarFormatCurrency");
+        break;
+      case 128:
+        asprintf(&name, "VarWeekdayName");
+        break;
+      case 129:
+        asprintf(&name, "VarMonthName");
+        break;
+      case 130:
+        asprintf(&name, "VarUI1FromI2");
+        break;
+      case 131:
+        asprintf(&name, "VarUI1FromI4");
+        break;
+      case 132:
+        asprintf(&name, "VarUI1FromR4");
+        break;
+      case 133:
+        asprintf(&name, "VarUI1FromR8");
+        break;
+      case 134:
+        asprintf(&name, "VarUI1FromCy");
+        break;
+      case 135:
+        asprintf(&name, "VarUI1FromDate");
+        break;
+      case 136:
+        asprintf(&name, "VarUI1FromStr");
+        break;
+      case 137:
+        asprintf(&name, "VarUI1FromDisp");
+        break;
+      case 138:
+        asprintf(&name, "VarUI1FromBool");
+        break;
+      case 139:
+        asprintf(&name, "VarFormatFromTokens");
+        break;
+      case 140:
+        asprintf(&name, "VarTokenizeFormatString");
+        break;
+      case 141:
+        asprintf(&name, "VarAdd");
+        break;
+      case 142:
+        asprintf(&name, "VarAnd");
+        break;
+      case 143:
+        asprintf(&name, "VarDiv");
+        break;
+      case 144:
+        asprintf(&name, "DllCanUnloadNow");
+        break;
+      case 145:
+        asprintf(&name, "DllGetClassObject");
+        break;
+      case 146:
+        asprintf(&name, "DispCallFunc");
+        break;
+      case 147:
+        asprintf(&name, "VariantChangeTypeEx");
+        break;
+      case 148:
+        asprintf(&name, "SafeArrayPtrOfIndex");
+        break;
+      case 149:
+        asprintf(&name, "SysStringByteLen");
+        break;
+      case 150:
+        asprintf(&name, "SysAllocStringByteLen");
+        break;
+      case 151:
+        asprintf(&name, "DllRegisterServer");
+        break;
+      case 152:
+        asprintf(&name, "VarEqv");
+        break;
+      case 153:
+        asprintf(&name, "VarIdiv");
+        break;
+      case 154:
+        asprintf(&name, "VarImp");
+        break;
+      case 155:
+        asprintf(&name, "VarMod");
+        break;
+      case 156:
+        asprintf(&name, "VarMul");
+        break;
+      case 157:
+        asprintf(&name, "VarOr");
+        break;
+      case 158:
+        asprintf(&name, "VarPow");
+        break;
+      case 159:
+        asprintf(&name, "VarSub");
+        break;
+      case 160:
+        asprintf(&name, "CreateTypeLib");
+        break;
+      case 161:
+        asprintf(&name, "LoadTypeLib");
+        break;
+      case 162:
+        asprintf(&name, "LoadRegTypeLib");
+        break;
+      case 163:
+        asprintf(&name, "RegisterTypeLib");
+        break;
+      case 164:
+        asprintf(&name, "QueryPathOfRegTypeLib");
+        break;
+      case 165:
+        asprintf(&name, "LHashValOfNameSys");
+        break;
+      case 166:
+        asprintf(&name, "LHashValOfNameSysA");
+        break;
+      case 167:
+        asprintf(&name, "VarXor");
+        break;
+      case 168:
+        asprintf(&name, "VarAbs");
+        break;
+      case 169:
+        asprintf(&name, "VarFix");
+        break;
+      case 170:
+        asprintf(&name, "OaBuildVersion");
+        break;
+      case 171:
+        asprintf(&name, "ClearCustData");
+        break;
+      case 172:
+        asprintf(&name, "VarInt");
+        break;
+      case 173:
+        asprintf(&name, "VarNeg");
+        break;
+      case 174:
+        asprintf(&name, "VarNot");
+        break;
+      case 175:
+        asprintf(&name, "VarRound");
+        break;
+      case 176:
+        asprintf(&name, "VarCmp");
+        break;
+      case 177:
+        asprintf(&name, "VarDecAdd");
+        break;
+      case 178:
+        asprintf(&name, "VarDecDiv");
+        break;
+      case 179:
+        asprintf(&name, "VarDecMul");
+        break;
+      case 180:
+        asprintf(&name, "CreateTypeLib2");
+        break;
+      case 181:
+        asprintf(&name, "VarDecSub");
+        break;
+      case 182:
+        asprintf(&name, "VarDecAbs");
+        break;
+      case 183:
+        asprintf(&name, "LoadTypeLibEx");
+        break;
+      case 184:
+        asprintf(&name, "SystemTimeToVariantTime");
+        break;
+      case 185:
+        asprintf(&name, "VariantTimeToSystemTime");
+        break;
+      case 186:
+        asprintf(&name, "UnRegisterTypeLib");
+        break;
+      case 187:
+        asprintf(&name, "VarDecFix");
+        break;
+      case 188:
+        asprintf(&name, "VarDecInt");
+        break;
+      case 189:
+        asprintf(&name, "VarDecNeg");
+        break;
+      case 190:
+        asprintf(&name, "VarDecFromUI1");
+        break;
+      case 191:
+        asprintf(&name, "VarDecFromI2");
+        break;
+      case 192:
+        asprintf(&name, "VarDecFromI4");
+        break;
+      case 193:
+        asprintf(&name, "VarDecFromR4");
+        break;
+      case 194:
+        asprintf(&name, "VarDecFromR8");
+        break;
+      case 195:
+        asprintf(&name, "VarDecFromDate");
+        break;
+      case 196:
+        asprintf(&name, "VarDecFromCy");
+        break;
+      case 197:
+        asprintf(&name, "VarDecFromStr");
+        break;
+      case 198:
+        asprintf(&name, "VarDecFromDisp");
+        break;
+      case 199:
+        asprintf(&name, "VarDecFromBool");
+        break;
+      case 200:
+        asprintf(&name, "GetErrorInfo");
+        break;
+      case 201:
+        asprintf(&name, "SetErrorInfo");
+        break;
+      case 202:
+        asprintf(&name, "CreateErrorInfo");
+        break;
+      case 203:
+        asprintf(&name, "VarDecRound");
+        break;
+      case 204:
+        asprintf(&name, "VarDecCmp");
+        break;
+      case 205:
+        asprintf(&name, "VarI2FromI1");
+        break;
+      case 206:
+        asprintf(&name, "VarI2FromUI2");
+        break;
+      case 207:
+        asprintf(&name, "VarI2FromUI4");
+        break;
+      case 208:
+        asprintf(&name, "VarI2FromDec");
+        break;
+      case 209:
+        asprintf(&name, "VarI4FromI1");
+        break;
+      case 210:
+        asprintf(&name, "VarI4FromUI2");
+        break;
+      case 211:
+        asprintf(&name, "VarI4FromUI4");
+        break;
+      case 212:
+        asprintf(&name, "VarI4FromDec");
+        break;
+      case 213:
+        asprintf(&name, "VarR4FromI1");
+        break;
+      case 214:
+        asprintf(&name, "VarR4FromUI2");
+        break;
+      case 215:
+        asprintf(&name, "VarR4FromUI4");
+        break;
+      case 216:
+        asprintf(&name, "VarR4FromDec");
+        break;
+      case 217:
+        asprintf(&name, "VarR8FromI1");
+        break;
+      case 218:
+        asprintf(&name, "VarR8FromUI2");
+        break;
+      case 219:
+        asprintf(&name, "VarR8FromUI4");
+        break;
+      case 220:
+        asprintf(&name, "VarR8FromDec");
+        break;
+      case 221:
+        asprintf(&name, "VarDateFromI1");
+        break;
+      case 222:
+        asprintf(&name, "VarDateFromUI2");
+        break;
+      case 223:
+        asprintf(&name, "VarDateFromUI4");
+        break;
+      case 224:
+        asprintf(&name, "VarDateFromDec");
+        break;
+      case 225:
+        asprintf(&name, "VarCyFromI1");
+        break;
+      case 226:
+        asprintf(&name, "VarCyFromUI2");
+        break;
+      case 227:
+        asprintf(&name, "VarCyFromUI4");
+        break;
+      case 228:
+        asprintf(&name, "VarCyFromDec");
+        break;
+      case 229:
+        asprintf(&name, "VarBstrFromI1");
+        break;
+      case 230:
+        asprintf(&name, "VarBstrFromUI2");
+        break;
+      case 231:
+        asprintf(&name, "VarBstrFromUI4");
+        break;
+      case 232:
+        asprintf(&name, "VarBstrFromDec");
+        break;
+      case 233:
+        asprintf(&name, "VarBoolFromI1");
+        break;
+      case 234:
+        asprintf(&name, "VarBoolFromUI2");
+        break;
+      case 235:
+        asprintf(&name, "VarBoolFromUI4");
+        break;
+      case 236:
+        asprintf(&name, "VarBoolFromDec");
+        break;
+      case 237:
+        asprintf(&name, "VarUI1FromI1");
+        break;
+      case 238:
+        asprintf(&name, "VarUI1FromUI2");
+        break;
+      case 239:
+        asprintf(&name, "VarUI1FromUI4");
+        break;
+      case 240:
+        asprintf(&name, "VarUI1FromDec");
+        break;
+      case 241:
+        asprintf(&name, "VarDecFromI1");
+        break;
+      case 242:
+        asprintf(&name, "VarDecFromUI2");
+        break;
+      case 243:
+        asprintf(&name, "VarDecFromUI4");
+        break;
+      case 244:
+        asprintf(&name, "VarI1FromUI1");
+        break;
+      case 245:
+        asprintf(&name, "VarI1FromI2");
+        break;
+      case 246:
+        asprintf(&name, "VarI1FromI4");
+        break;
+      case 247:
+        asprintf(&name, "VarI1FromR4");
+        break;
+      case 248:
+        asprintf(&name, "VarI1FromR8");
+        break;
+      case 249:
+        asprintf(&name, "VarI1FromDate");
+        break;
+      case 250:
+        asprintf(&name, "VarI1FromCy");
+        break;
+      case 251:
+        asprintf(&name, "VarI1FromStr");
+        break;
+      case 252:
+        asprintf(&name, "VarI1FromDisp");
+        break;
+      case 253:
+        asprintf(&name, "VarI1FromBool");
+        break;
+      case 254:
+        asprintf(&name, "VarI1FromUI2");
+        break;
+      case 255:
+        asprintf(&name, "VarI1FromUI4");
+        break;
+      case 256:
+        asprintf(&name, "VarI1FromDec");
+        break;
+      case 257:
+        asprintf(&name, "VarUI2FromUI1");
+        break;
+      case 258:
+        asprintf(&name, "VarUI2FromI2");
+        break;
+      case 259:
+        asprintf(&name, "VarUI2FromI4");
+        break;
+      case 260:
+        asprintf(&name, "VarUI2FromR4");
+        break;
+      case 261:
+        asprintf(&name, "VarUI2FromR8");
+        break;
+      case 262:
+        asprintf(&name, "VarUI2FromDate");
+        break;
+      case 263:
+        asprintf(&name, "VarUI2FromCy");
+        break;
+      case 264:
+        asprintf(&name, "VarUI2FromStr");
+        break;
+      case 265:
+        asprintf(&name, "VarUI2FromDisp");
+        break;
+      case 266:
+        asprintf(&name, "VarUI2FromBool");
+        break;
+      case 267:
+        asprintf(&name, "VarUI2FromI1");
+        break;
+      case 268:
+        asprintf(&name, "VarUI2FromUI4");
+        break;
+      case 269:
+        asprintf(&name, "VarUI2FromDec");
+        break;
+      case 270:
+        asprintf(&name, "VarUI4FromUI1");
+        break;
+      case 271:
+        asprintf(&name, "VarUI4FromI2");
+        break;
+      case 272:
+        asprintf(&name, "VarUI4FromI4");
+        break;
+      case 273:
+        asprintf(&name, "VarUI4FromR4");
+        break;
+      case 274:
+        asprintf(&name, "VarUI4FromR8");
+        break;
+      case 275:
+        asprintf(&name, "VarUI4FromDate");
+        break;
+      case 276:
+        asprintf(&name, "VarUI4FromCy");
+        break;
+      case 277:
+        asprintf(&name, "VarUI4FromStr");
+        break;
+      case 278:
+        asprintf(&name, "VarUI4FromDisp");
+        break;
+      case 279:
+        asprintf(&name, "VarUI4FromBool");
+        break;
+      case 280:
+        asprintf(&name, "VarUI4FromI1");
+        break;
+      case 281:
+        asprintf(&name, "VarUI4FromUI2");
+        break;
+      case 282:
+        asprintf(&name, "VarUI4FromDec");
+        break;
+      case 283:
+        asprintf(&name, "BSTR_UserSize");
+        break;
+      case 284:
+        asprintf(&name, "BSTR_UserMarshal");
+        break;
+      case 285:
+        asprintf(&name, "BSTR_UserUnmarshal");
+        break;
+      case 286:
+        asprintf(&name, "BSTR_UserFree");
+        break;
+      case 287:
+        asprintf(&name, "VARIANT_UserSize");
+        break;
+      case 288:
+        asprintf(&name, "VARIANT_UserMarshal");
+        break;
+      case 289:
+        asprintf(&name, "VARIANT_UserUnmarshal");
+        break;
+      case 290:
+        asprintf(&name, "VARIANT_UserFree");
+        break;
+      case 291:
+        asprintf(&name, "LPSAFEARRAY_UserSize");
+        break;
+      case 292:
+        asprintf(&name, "LPSAFEARRAY_UserMarshal");
+        break;
+      case 293:
+        asprintf(&name, "LPSAFEARRAY_UserUnmarshal");
+        break;
+      case 294:
+        asprintf(&name, "LPSAFEARRAY_UserFree");
+        break;
+      case 295:
+        asprintf(&name, "LPSAFEARRAY_Size");
+        break;
+      case 296:
+        asprintf(&name, "LPSAFEARRAY_Marshal");
+        break;
+      case 297:
+        asprintf(&name, "LPSAFEARRAY_Unmarshal");
+        break;
+      case 298:
+        asprintf(&name, "VarDecCmpR8");
+        break;
+      case 299:
+        asprintf(&name, "VarCyAdd");
+        break;
+      case 300:
+        asprintf(&name, "DllUnregisterServer");
+        break;
+      case 301:
+        asprintf(&name, "OACreateTypeLib2");
+        break;
+      case 303:
+        asprintf(&name, "VarCyMul");
+        break;
+      case 304:
+        asprintf(&name, "VarCyMulI4");
+        break;
+      case 305:
+        asprintf(&name, "VarCySub");
+        break;
+      case 306:
+        asprintf(&name, "VarCyAbs");
+        break;
+      case 307:
+        asprintf(&name, "VarCyFix");
+        break;
+      case 308:
+        asprintf(&name, "VarCyInt");
+        break;
+      case 309:
+        asprintf(&name, "VarCyNeg");
+        break;
+      case 310:
+        asprintf(&name, "VarCyRound");
+        break;
+      case 311:
+        asprintf(&name, "VarCyCmp");
+        break;
+      case 312:
+        asprintf(&name, "VarCyCmpR8");
+        break;
+      case 313:
+        asprintf(&name, "VarBstrCat");
+        break;
+      case 314:
+        asprintf(&name, "VarBstrCmp");
+        break;
+      case 315:
+        asprintf(&name, "VarR8Pow");
+        break;
+      case 316:
+        asprintf(&name, "VarR4CmpR8");
+        break;
+      case 317:
+        asprintf(&name, "VarR8Round");
+        break;
+      case 318:
+        asprintf(&name, "VarCat");
+        break;
+      case 319:
+        asprintf(&name, "VarDateFromUdateEx");
+        break;
+      case 322:
+        asprintf(&name, "GetRecordInfoFromGuids");
+        break;
+      case 323:
+        asprintf(&name, "GetRecordInfoFromTypeInfo");
+        break;
+      case 325:
+        asprintf(&name, "SetVarConversionLocaleSetting");
+        break;
+      case 326:
+        asprintf(&name, "GetVarConversionLocaleSetting");
+        break;
+      case 327:
+        asprintf(&name, "SetOaNoCache");
+        break;
+      case 329:
+        asprintf(&name, "VarCyMulI8");
+        break;
+      case 330:
+        asprintf(&name, "VarDateFromUdate");
+        break;
+      case 331:
+        asprintf(&name, "VarUdateFromDate");
+        break;
+      case 332:
+        asprintf(&name, "GetAltMonthNames");
+        break;
+      case 333:
+        asprintf(&name, "VarI8FromUI1");
+        break;
+      case 334:
+        asprintf(&name, "VarI8FromI2");
+        break;
+      case 335:
+        asprintf(&name, "VarI8FromR4");
+        break;
+      case 336:
+        asprintf(&name, "VarI8FromR8");
+        break;
+      case 337:
+        asprintf(&name, "VarI8FromCy");
+        break;
+      case 338:
+        asprintf(&name, "VarI8FromDate");
+        break;
+      case 339:
+        asprintf(&name, "VarI8FromStr");
+        break;
+      case 340:
+        asprintf(&name, "VarI8FromDisp");
+        break;
+      case 341:
+        asprintf(&name, "VarI8FromBool");
+        break;
+      case 342:
+        asprintf(&name, "VarI8FromI1");
+        break;
+      case 343:
+        asprintf(&name, "VarI8FromUI2");
+        break;
+      case 344:
+        asprintf(&name, "VarI8FromUI4");
+        break;
+      case 345:
+        asprintf(&name, "VarI8FromDec");
+        break;
+      case 346:
+        asprintf(&name, "VarI2FromI8");
+        break;
+      case 347:
+        asprintf(&name, "VarI2FromUI8");
+        break;
+      case 348:
+        asprintf(&name, "VarI4FromI8");
+        break;
+      case 349:
+        asprintf(&name, "VarI4FromUI8");
+        break;
+      case 360:
+        asprintf(&name, "VarR4FromI8");
+        break;
+      case 361:
+        asprintf(&name, "VarR4FromUI8");
+        break;
+      case 362:
+        asprintf(&name, "VarR8FromI8");
+        break;
+      case 363:
+        asprintf(&name, "VarR8FromUI8");
+        break;
+      case 364:
+        asprintf(&name, "VarDateFromI8");
+        break;
+      case 365:
+        asprintf(&name, "VarDateFromUI8");
+        break;
+      case 366:
+        asprintf(&name, "VarCyFromI8");
+        break;
+      case 367:
+        asprintf(&name, "VarCyFromUI8");
+        break;
+      case 368:
+        asprintf(&name, "VarBstrFromI8");
+        break;
+      case 369:
+        asprintf(&name, "VarBstrFromUI8");
+        break;
+      case 370:
+        asprintf(&name, "VarBoolFromI8");
+        break;
+      case 371:
+        asprintf(&name, "VarBoolFromUI8");
+        break;
+      case 372:
+        asprintf(&name, "VarUI1FromI8");
+        break;
+      case 373:
+        asprintf(&name, "VarUI1FromUI8");
+        break;
+      case 374:
+        asprintf(&name, "VarDecFromI8");
+        break;
+      case 375:
+        asprintf(&name, "VarDecFromUI8");
+        break;
+      case 376:
+        asprintf(&name, "VarI1FromI8");
+        break;
+      case 377:
+        asprintf(&name, "VarI1FromUI8");
+        break;
+      case 378:
+        asprintf(&name, "VarUI2FromI8");
+        break;
+      case 379:
+        asprintf(&name, "VarUI2FromUI8");
+        break;
+      case 401:
+        asprintf(&name, "OleLoadPictureEx");
+        break;
+      case 402:
+        asprintf(&name, "OleLoadPictureFileEx");
+        break;
+      case 411:
+        asprintf(&name, "SafeArrayCreateVector");
+        break;
+      case 412:
+        asprintf(&name, "SafeArrayCopyData");
+        break;
+      case 413:
+        asprintf(&name, "VectorFromBstr");
+        break;
+      case 414:
+        asprintf(&name, "BstrFromVector");
+        break;
+      case 415:
+        asprintf(&name, "OleIconToCursor");
+        break;
+      case 416:
+        asprintf(&name, "OleCreatePropertyFrameIndirect");
+        break;
+      case 417:
+        asprintf(&name, "OleCreatePropertyFrame");
+        break;
+      case 418:
+        asprintf(&name, "OleLoadPicture");
+        break;
+      case 419:
+        asprintf(&name, "OleCreatePictureIndirect");
+        break;
+      case 420:
+        asprintf(&name, "OleCreateFontIndirect");
+        break;
+      case 421:
+        asprintf(&name, "OleTranslateColor");
+        break;
+      case 422:
+        asprintf(&name, "OleLoadPictureFile");
+        break;
+      case 423:
+        asprintf(&name, "OleSavePictureFile");
+        break;
+      case 424:
+        asprintf(&name, "OleLoadPicturePath");
+        break;
+      case 425:
+        asprintf(&name, "VarUI4FromI8");
+        break;
+      case 426:
+        asprintf(&name, "VarUI4FromUI8");
+        break;
+      case 427:
+        asprintf(&name, "VarI8FromUI8");
+        break;
+      case 428:
+        asprintf(&name, "VarUI8FromI8");
+        break;
+      case 429:
+        asprintf(&name, "VarUI8FromUI1");
+        break;
+      case 430:
+        asprintf(&name, "VarUI8FromI2");
+        break;
+      case 431:
+        asprintf(&name, "VarUI8FromR4");
+        break;
+      case 432:
+        asprintf(&name, "VarUI8FromR8");
+        break;
+      case 433:
+        asprintf(&name, "VarUI8FromCy");
+        break;
+      case 434:
+        asprintf(&name, "VarUI8FromDate");
+        break;
+      case 435:
+        asprintf(&name, "VarUI8FromStr");
+        break;
+      case 436:
+        asprintf(&name, "VarUI8FromDisp");
+        break;
+      case 437:
+        asprintf(&name, "VarUI8FromBool");
+        break;
+      case 438:
+        asprintf(&name, "VarUI8FromI1");
+        break;
+      case 439:
+        asprintf(&name, "VarUI8FromUI2");
+        break;
+      case 440:
+        asprintf(&name, "VarUI8FromUI4");
+        break;
+      case 441:
+        asprintf(&name, "VarUI8FromDec");
+        break;
+      case 442:
+        asprintf(&name, "RegisterTypeLibForUser");
+        break;
+      case 443:
+        asprintf(&name, "UnRegisterTypeLibForUser");
+        break;
+      default:
+        break;
+    }
+  }
+  if (!name)
+    asprintf(&name, "ord%u", ord);
+  return name;
+}
 
 PIMAGE_NT_HEADERS32 pe_get_header(
     uint8_t* data,
@@ -702,38 +2300,135 @@ define_function(exports)
 }
 
 
-define_function(imports)
+/*
+ * Generate an import hash:
+ * https://www.mandiant.com/blog/tracking-malware-import-hashing/
+ * It is important to make duplicates of the strings as we don't want
+ * to alter the contents of the parsed import structures.
+ */
+// XXX: Add -lcrypto to Makefile.am
+define_function(imphash)
 {
-  char* dll_name = string_argument(1);
-  char* function_name = string_argument(2);
-  int function_name_len = strlen(function_name);
-
+  char *p;
+  char *dll_name;
+  char *final_name;
+  size_t len;
+  int i;
+  unsigned int md_len;
+  EVP_MD_CTX mdctx;
+  unsigned char md_value[EVP_MAX_MD_SIZE];
+  char *final_hash;
+  char *hash = string_argument(1);
+  int first = 1;
+  int result = 0;
+  PIMPORT_LIST cur_dll_node = NULL;
+  PIMPORT_FUNC_LIST cur_func_node = NULL;
   YR_OBJECT* module = module();
   PE* pe = (PE*) module->data;
+  const EVP_MD *md = EVP_md5();
+
+  // If not a PE, return 0.
+  if (!pe)
+    return_integer(result);
+
+  EVP_MD_CTX_init(&mdctx);
+  EVP_DigestInit_ex(&mdctx, md, NULL);
+
+  cur_dll_node = pe->imports;
+  while (cur_dll_node) {
+    // If extension is 'ocx', 'sys' or 'dll', chop it.
+    p = strstr(cur_dll_node->dll, ".");
+    if (p && (strncasecmp(p, ".ocx", 4) == 0 ||
+              strncasecmp(p, ".sys", 4) == 0 ||
+              strncasecmp(p, ".dll", 4) == 0)) {
+      len = (p - cur_dll_node->dll) + 1;
+    }
+    else {
+      len = strlen(cur_dll_node->dll) + 1;
+    }
+
+    // Allocate a new string to hold the dll name.
+    dll_name = (char *) yr_malloc(len);
+    strlcpy(dll_name, cur_dll_node->dll, len);
+
+    cur_func_node = cur_dll_node->names;
+    while (cur_func_node) {
+      if (first == 1) {
+        asprintf(&final_name, "%s.%s", dll_name, cur_func_node->name);
+        first = 0;
+      } else {
+        asprintf(&final_name, ",%s.%s", dll_name, cur_func_node->name);
+        first = 0;
+      }
+
+      // Lowercase the whole thing.
+      for (i = 0; i < strlen(final_name); i++) {
+        final_name[i] = tolower(final_name[i]);
+      }
+
+      EVP_DigestUpdate(&mdctx, final_name, strlen(final_name));
+
+      yr_free(final_name);
+      cur_func_node = cur_func_node->next;
+    }
+
+    yr_free(dll_name);
+    cur_dll_node = cur_dll_node->next;
+  }
+
+  EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
+  EVP_MD_CTX_cleanup(&mdctx);
+
+  // Convert md_value into it's hexlified form.
+  final_hash = yr_malloc((md_len * 2));
+  if (!final_hash)
+    return_integer(0);
+
+  p = final_hash;
+  for (i = 0; i < md_len; i++)
+    snprintf(p + 2 * i, 3, "%02x", md_value[i]);
+
+  if (strncasecmp(hash, final_hash, (md_len * 2)) == 0)
+    result = 1;
 
+  yr_free(final_hash);
+  return_integer(result);
+}
+
+
+/*
+ * Walk the imports and collect relevant information. It is used in the
+ * "imports" function for comparison and in the "imphash" function for
+ * calculation.
+ */
+PIMPORT_LIST parse_imports(PE* pe)
+{
   PIMAGE_DATA_DIRECTORY directory;
   PIMAGE_IMPORT_DESCRIPTOR imports;
   PIMAGE_IMPORT_BY_NAME import;
   PIMAGE_THUNK_DATA32 thunks32;
   PIMAGE_THUNK_DATA64 thunks64;
+  PIMPORT_LIST dll_head = NULL;
+  PIMPORT_LIST cur_dll_node = NULL;
+  PIMPORT_LIST new_dll_node = NULL;
+  PIMPORT_FUNC_LIST cur_func_node = NULL;
+  PIMPORT_FUNC_LIST new_func_node = NULL;
 
+  size_t size;
   uint64_t offset;
-
-  // if not a PE file, return UNDEFINED
-
-  if (pe == NULL)
-    return_integer(UNDEFINED);
+  uint16_t ordinal;
+  char *ord_name;
 
   directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_IMPORT);
 
   if (directory->VirtualAddress == 0)
-    return_integer(0);
+    return NULL;
 
   offset = pe_rva_to_offset(pe, directory->VirtualAddress);
 
   if (offset == 0 ||
       offset + sizeof(IMAGE_IMPORT_DESCRIPTOR) > pe->data_size)
-    return_integer(0);
+    return NULL;
 
   imports = (PIMAGE_IMPORT_DESCRIPTOR)(pe->data + offset);
 
@@ -742,13 +2437,23 @@ define_function(imports)
   {
     offset = pe_rva_to_offset(pe, imports->Name);
 
-    if (offset > 0 &&
-        offset <= pe->data_size &&
-        strncasecmp(
-            dll_name,
-            (char*)(pe->data + offset),
-            pe->data_size - offset) == 0)
+    if (offset > 0 && offset <= pe->data_size)
     {
+      new_dll_node = (PIMPORT_LIST) yr_malloc(sizeof(IMPORT_LIST));
+      if (!new_dll_node)
+        return NULL;
+
+      if (dll_head == NULL)
+        dll_head = new_dll_node;
+
+      if (cur_dll_node != NULL)
+        cur_dll_node->next = new_dll_node;
+
+      cur_dll_node = new_dll_node;
+
+      // Store the DLL name.
+      cur_dll_node->dll = yr_strdup((char *) (pe->data + offset));
+
       offset = pe_rva_to_offset(pe, imports->OriginalFirstThunk);
 
       if (offset > 0)
@@ -770,20 +2475,55 @@ define_function(imports)
               {
                 import = (PIMAGE_IMPORT_BY_NAME)(pe->data + offset);
 
-                if (fits_in_pe(pe, import->Name, function_name_len))
-                {
-                  if (strncmp((char*) import->Name,
-                              function_name,
-                              function_name_len) == 0)
-                  {
-                    return_integer(1);
-                  }
-                }
+                /*
+                 * Make sure there is a NULL byte somewhere between
+                 * import->Name and the end of PE. If strnlen() can't find the
+                 * end of the string, it will return the number of bytes until
+                 * the end of PE. If this happens, return.
+                 */
+                size = strnlen((char *) import->Name, (pe->data + pe->data_size) - import->Name);
+                if (size == (pe->data + pe->data_size) - import->Name)
+                  return NULL;
+
+                new_func_node = (PIMPORT_FUNC_LIST) yr_malloc(sizeof(IMPORT_FUNC_LIST));
+                if (!new_func_node)
+                  return NULL;
+
+                if (cur_func_node != NULL)
+                  cur_func_node->next = new_func_node;
+
+                cur_func_node = new_func_node;
+                if (cur_dll_node->names == NULL)
+                  cur_dll_node->names = cur_func_node;
+
+                // Store the function name.
+                cur_func_node->name = yr_strdup((char *) import->Name);
               }
             }
-
+            else
+            {
+              // Exported by ordinal.
+              ordinal = thunks64->u1.Ordinal & 0xFFFF;
+              new_func_node = (PIMPORT_FUNC_LIST) yr_malloc(sizeof(IMPORT_FUNC_LIST));
+              if (!new_func_node)
+                return NULL;
+
+              if (cur_func_node != NULL)
+                cur_func_node->next = new_func_node;
+
+              cur_func_node = new_func_node;
+              if (cur_dll_node->names == NULL)
+                cur_dll_node->names = cur_func_node;
+
+              // Lookup the ordinal.
+              ord_name = ord_lookup(cur_dll_node->dll, ordinal);
+              if (ord_name == NULL)
+                return NULL;
+              cur_func_node->name = yr_strdup(ord_name);
+            }
             thunks64++;
           }
+          cur_func_node = NULL;
         }
         else
         {
@@ -802,20 +2542,55 @@ define_function(imports)
               {
                 import = (PIMAGE_IMPORT_BY_NAME)(pe->data + offset);
 
-                if (fits_in_pe(pe, import->Name, function_name_len))
-                {
-                  if (strncmp((char*) import->Name,
-                              function_name,
-                              function_name_len) == 0)
-                  {
-                    return_integer(1);
-                  }
-                }
+                /*
+                 * Make sure there is a NULL byte somewhere between
+                 * import->Name and the end of PE. If strnlen() can't find the
+                 * end of the string, it will return the number of bytes until
+                 * the end of PE. If this happens, return.
+                 */
+                size = strnlen((char *) import->Name, (pe->data + pe->data_size) - import->Name);
+                if (size == (pe->data + pe->data_size) - import->Name)
+                  return NULL;
+
+                new_func_node = (PIMPORT_FUNC_LIST) yr_malloc(sizeof(IMPORT_FUNC_LIST));
+                if (!new_func_node)
+                  return NULL;
+
+                if (cur_func_node != NULL)
+                  cur_func_node->next = new_func_node;
+
+                cur_func_node = new_func_node;
+                if (cur_dll_node->names == NULL)
+                  cur_dll_node->names = cur_func_node;
+
+                // Store the function name.
+                cur_func_node->name = yr_strdup((char *) import->Name);
               }
             }
-
+            else
+            {
+              // Exported by ordinal.
+              ordinal = thunks32->u1.Ordinal & 0xFFFF;
+              new_func_node = (PIMPORT_FUNC_LIST) yr_malloc(sizeof(IMPORT_FUNC_LIST));
+              if (!new_func_node)
+                return NULL;
+
+              if (cur_func_node != NULL)
+                cur_func_node->next = new_func_node;
+
+              cur_func_node = new_func_node;
+              if (cur_dll_node->names == NULL)
+                cur_dll_node->names = cur_func_node;
+
+              // Lookup the ordinal.
+              ord_name = ord_lookup(cur_dll_node->dll, ordinal);
+              if (ord_name == NULL)
+                return NULL;
+              cur_func_node->name = yr_strdup(ord_name);
+            }
             thunks32++;
           }
+          cur_func_node = NULL;
         }
       }
     }
@@ -823,6 +2598,38 @@ define_function(imports)
     imports++;
   }
 
+  return dll_head;
+}
+
+
+define_function(imports)
+{
+  PIMPORT_LIST cur_dll_node = NULL;
+  PIMPORT_FUNC_LIST cur_func_node = NULL;
+  char* dll_name = string_argument(1);
+  char* function_name = string_argument(2);
+  int function_name_len = strlen(function_name);
+  int dll_name_len = strlen(dll_name);
+
+  YR_OBJECT* module = module();
+  PE* pe = (PE*) module->data;
+
+  cur_dll_node = pe->imports;
+  while (cur_dll_node)
+  {
+    if (strncasecmp(cur_dll_node->dll, dll_name, dll_name_len) == 0)
+    {
+      cur_func_node = cur_dll_node->names;
+      while (cur_func_node)
+      {
+        if (strncasecmp(cur_func_node->name, function_name, function_name_len) == 0)
+          return_integer(1);
+        cur_func_node = cur_func_node->next;
+      }
+    }
+    cur_dll_node = cur_dll_node->next;
+  }
+
   return_integer(0);
 }
 
@@ -993,6 +2800,7 @@ begin_declarations;
   declare_function("imports", "ss", "i", imports);
   declare_function("locale", "i", "i", locale);
   declare_function("language", "i", "i", language);
+  declare_function("imphash", "s", "i", imphash);
 
 end_declarations;
 
@@ -1127,6 +2935,8 @@ int module_load(
             block->base,
             context->flags);
 
+        PIMPORT_LIST import_list = parse_imports(pe);
+        pe->imports = import_list;
         break;
       }
     }
@@ -1138,6 +2948,10 @@ int module_load(
 
 int module_unload(YR_OBJECT* module_object)
 {
+  PIMPORT_LIST cur_dll_node = NULL;
+  PIMPORT_LIST next_dll_node = NULL;
+  PIMPORT_FUNC_LIST cur_func_node = NULL;
+  PIMPORT_FUNC_LIST next_func_node = NULL;
   PE* pe = (PE *) module_object->data;
   if (pe != NULL) {
     if (pe->rich_data) {
@@ -1147,6 +2961,20 @@ int module_unload(YR_OBJECT* module_object)
         yr_free(pe->rich_data->clear_data);
       yr_free(pe->rich_data);
     }
+    if (pe->imports) {
+      cur_dll_node = pe->imports;
+      while (cur_dll_node) {
+        cur_func_node = cur_dll_node->names;
+        while (cur_func_node) {
+          next_func_node = cur_func_node->next;
+          yr_free(cur_func_node);
+          cur_func_node = next_func_node;
+        }
+        next_dll_node = cur_dll_node->next;
+        yr_free(cur_dll_node);
+        cur_dll_node = next_dll_node;
+      }
+    }
     yr_free(module_object->data);
   }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list