{"id":80,"date":"2011-06-08T23:09:29","date_gmt":"2011-06-08T21:09:29","guid":{"rendered":"http:\/\/blog.rewolf.pl\/blog\/?p=80"},"modified":"2013-08-18T13:01:45","modified_gmt":"2013-08-18T11:01:45","slug":"upx-accidentally-increments-loadcount-for-dlls","status":"publish","type":"post","link":"http:\/\/blog.rewolf.pl\/blog\/?p=80","title":{"rendered":"UPX &#8220;accidentally&#8221; increments LoadCount for DLLs"},"content":{"rendered":"<p style=\"text-align: justify;\">When I was preparing last <a href=\"http:\/\/dirty-joe.com\">dirtyJOE<\/a> update I&#8217;ve noticed that under some circumstances python DLLs are not freed from memory. What was even more interesting, this behaviour was occurring only in ready to release version of application. I&#8217;ve tested few scenarios and I figured out that the problem lays in <strong>UPX <\/strong>loader.<\/p>\n<p style=\"text-align: justify;\">I&#8217;ll try to explain what exactly happens.<\/p>\n<p><!--more--><br \/>\nPrerequisites:<\/p>\n<ul>\n<li> there are two DLLs (preinstalled.dll, mylib.dll) and main executable (test.exe)<\/li>\n<li> import table of mylib.dll contains references to preinstalled.dll<\/li>\n<li> test.exe dynamically loads both libs<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Scenario:<\/p>\n<ol>\n<li style=\"text-align: justify;\"> test.exe tries to load preinstalled.dll (to check if it was installed in the system)<\/li>\n<li style=\"text-align: justify;\"> if it succeed <strong>LoadCount<\/strong> field in <strong>_LDR_DATA_TABLE_ENTRY<\/strong> will be incremented (<strong>LoadCount = 1<\/strong>)<\/li>\n<li style=\"text-align: justify;\"> test.exe now can try to load mylib.dll (without successful step 1, system will show ugly <strong>MessageBox <\/strong>about lacking of preinstalled.dll)<\/li>\n<li style=\"text-align: justify;\"> if everything is ok <strong>LoadCount <\/strong>of preinstalled.dll should be incremented (<strong>LoadCount = 2<\/strong>)<\/li>\n<li style=\"text-align: justify;\"> (&#8230;)<\/li>\n<li style=\"text-align: justify;\">free mylib.dll, <strong>LoadCount <\/strong>of preinstalled.dll should be decremented (<strong>LoadCount = 1<\/strong>)<\/li>\n<li style=\"text-align: justify;\"> free preinstalled.dll, <strong>LoadCount <\/strong>decrementation (<strong>LoadCount = 0<\/strong>)<\/li>\n<li style=\"text-align: justify;\"> system unmaps preinstalled.dll from application memory<\/li>\n<\/ol>\n<p style=\"text-align: justify;\">Pseudocode:<\/p>\n<pre style=\"background-color: #eaeaea; color: black;\">\tHMODULE hPreInst = LoadLibrary(\"preinstalled.dll\");\r\n\tif (0 == hPreInst)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\/\/<span style=\"color: #008000;\"><strong>LoadCount = 1<\/strong><\/span>\r\n\r\n\tHMODULE hMyLib = LoadLibrary(\"mylib.dll\");\r\n\tif (0 == hMyLib)\r\n\t{\r\n\t\tFreeLibrary(hPreInst);\r\n\t\treturn;\r\n\t}\r\n\t\/\/<span style=\"color: #008000;\"><strong>LoadCount = 2<\/strong><\/span>\r\n\r\n\t\/\/do some stuff here, it doesn't matter what ;)\r\n\r\n\tFreeLibrary(hMyLib);\t\t\/\/<span style=\"color: #008000;\"><strong>LoadCount = 1<\/strong><\/span>\r\n\tFreeLibrary(hPreInst);\t\t\/\/<span style=\"color: #008000;\"><strong>LoadCount = 0<\/strong><\/span>, library is unmaped from the memory<\/pre>\n<p style=\"text-align: justify;\">In above situation everything is clear and works perfectly until someone will not pack mylib.dll with <strong>UPX <\/strong>(or any other packer with similar imports handling). For stability(?) and compatibility(?) reasons <strong>UPX <\/strong>keeps one imported function from every referenced library (except <strong>kernel32<\/strong>):<\/p>\n<table align=\"center\">\n<thead>\n<tr>\n<td><strong><span style=\"color: #c0c0c0;\">Original imports table<\/span><\/strong><\/td>\n<td><strong><span style=\"color: #c0c0c0;\">UPX imports table<\/span><\/strong><\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td valign=\"top\"><strong><span style=\"color: #c0c0c0;\">Kernel32.dll<\/span> <\/strong>&nbsp;<\/p>\n<ul>\n<li><span style=\"color: #c0c0c0;\">func1<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">func2<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">func3<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">&#8230;<\/span><\/li>\n<\/ul>\n<\/td>\n<td valign=\"top\"><strong><span style=\"color: #c0c0c0;\">Kernel32.dll<\/span> <\/strong>&nbsp;<\/p>\n<ul>\n<li><span style=\"color: #c0c0c0;\">LoadLibraryA<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">GetProcAddress<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">VirtualProtect<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">VirtualAlloc<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">VirtualFree<\/span><\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\"><strong><span style=\"color: #c0c0c0;\">mylib.dll<\/span> <\/strong>&nbsp;<\/p>\n<ul>\n<li><span style=\"color: #c0c0c0;\">func1<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">func2<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">func3<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">&#8230;<\/span><\/li>\n<\/ul>\n<\/td>\n<td valign=\"top\"><strong><span style=\"color: #c0c0c0;\">mylib.dll<\/span> <\/strong>&nbsp;<\/p>\n<ul>\n<li><span style=\"color: #c0c0c0;\">func1<\/span><\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\"><strong><span style=\"color: #c0c0c0;\">xxxx.dll<\/span> <\/strong>&nbsp;<\/p>\n<ul>\n<li><span style=\"color: #c0c0c0;\">func1<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">func2<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">func3<\/span><\/li>\n<li><span style=\"color: #c0c0c0;\">&#8230;<\/span><\/li>\n<\/ul>\n<\/td>\n<td valign=\"top\"><strong><span style=\"color: #c0c0c0;\">xxxx.dll<\/span> <\/strong>&nbsp;<\/p>\n<ul>\n<li><span style=\"color: #c0c0c0;\">func1<\/span><\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p style=\"text-align: justify;\"><strong>UPX <\/strong>loader is responsible for filling proper addresses in <strong>IAT<\/strong>:<\/p>\n<pre style=\"background-color: #eaeaea; color: black;\">\tlea\u00a0\u00a0\u00a0\u00a0 edi, [esi+10000h]\r\n\r\n<span style=\"color: #0000ff;\">_next_library<\/span>:\r\n\tmov\u00a0\u00a0\u00a0\u00a0 eax, [edi]\r\n\tor\u00a0\u00a0\u00a0\u00a0\u00a0 eax, eax\r\n\tjz\u00a0\u00a0\u00a0\u00a0\u00a0 short <span style=\"color: #0000ff;\">_imports_end<\/span>\r\n\tmov\u00a0\u00a0\u00a0\u00a0 ebx, [edi+4]\r\n\tlea\u00a0\u00a0\u00a0\u00a0 eax, [eax+esi+121B8h]\r\n\tadd\u00a0\u00a0\u00a0\u00a0 ebx, esi\r\n\tpush\u00a0\u00a0\u00a0 eax\r\n\tadd\u00a0\u00a0\u00a0\u00a0 edi, 8\r\n\t<span style=\"color: #ff0000;\"><strong>call\u00a0\u00a0\u00a0 dword ptr [esi+121F4h] ; LoadLibraryA<\/strong><\/span>\r\n\txchg\u00a0\u00a0\u00a0 eax, ebp\r\n\r\n<span style=\"color: #0000ff;\">_next_function<\/span>:\r\n\tmov\u00a0\u00a0\u00a0\u00a0 al, [edi]\r\n\tinc\u00a0\u00a0\u00a0\u00a0 edi\r\n\tor\u00a0\u00a0\u00a0\u00a0\u00a0 al, al\r\n\tjz\u00a0\u00a0\u00a0\u00a0\u00a0 short <span style=\"color: #0000ff;\">_next_library<\/span>\r\n\tmov\u00a0\u00a0\u00a0\u00a0 ecx, edi\r\n\tpush\u00a0\u00a0\u00a0 edi\r\n\tdec\u00a0\u00a0\u00a0\u00a0 eax\r\n\trepne scasb\r\n\tpush\u00a0\u00a0\u00a0 ebp\r\n\tcall\u00a0\u00a0\u00a0 dword ptr [esi+121F8h] ; GetProcAddress\r\n\tor\u00a0\u00a0\u00a0\u00a0\u00a0 eax, eax\r\n\tjz\u00a0\u00a0\u00a0\u00a0\u00a0 short <span style=\"color: #0000ff;\">_gpa_error<\/span>\r\n\tmov\u00a0\u00a0\u00a0\u00a0 [ebx], eax\r\n\tadd\u00a0\u00a0\u00a0\u00a0 ebx, 4\r\n\tjmp\u00a0\u00a0\u00a0\u00a0 short <span style=\"color: #0000ff;\">_next_function\r\n\r\n_gpa_error<\/span>:\r\n\tpopa\r\n\txor\u00a0\u00a0\u00a0\u00a0 eax, eax\r\n\tretn\u00a0\u00a0\u00a0 0Ch\r\n\r\n<span style=\"color: #0000ff;\">_imports_end<\/span>:<\/pre>\n<p>Let&#8217;s back to previous pseudocode:<\/p>\n<pre style=\"background-color: #eaeaea; color: black;\">\tHMODULE hPreInst = LoadLibrary(\"preinstalled.dll\");\r\n\tif (0 == hPreInst)\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t\/\/LoadCount = 1\r\n\r\n\tHMODULE hMyLib = LoadLibrary(\"mylib.dll\");\u00a0\u00a0\u00a0 \/\/<span style=\"color: #ff0000;\"><strong>mylib.dll is packed by UPX now !!!<\/strong><\/span>\r\n\t\/*\r\n<span style=\"color: #ff0000;\"><strong>\t\tActions taken behind our back:\r\n\t\t- loading UPX imports table from preinstalled.dll by windows loader,\r\n\t\t  LoadCount = 2\r\n\t\t- loading original imports table from preinstalled.dll by UPX loader,\r\n\t\t  LoadCount = 3<\/strong><\/span>\r\n\t*\/\r\n\tif (0 == hMyLib)\r\n\t{\r\n\t\tFreeLibrary(hPreInst);\r\n\t\treturn;\r\n\t}\r\n\t\/\/<span style=\"color: #ff0000;\"><strong>LoadCount = 3 !!!<\/strong><\/span>\r\n\r\n\t\/\/do some stuff here, it doesn't matter what ;)\r\n\r\n\tFreeLibrary(hMyLib);\t\t\/\/<strong><span style=\"color: #ff0000;\">LoadCount = 2<\/span><\/strong>\r\n\tFreeLibrary(hPreInst);\t\t\/\/<span style=\"color: #ff0000;\"><strong>LoadCount = 1, library will stay in memory !!!<\/strong><\/span><\/pre>\n<p style=\"text-align: justify;\">Now, there is one simple question (or maybe not that simple ?): why don&#8217;t use <strong>GetModuleHandleA <\/strong>instead of <strong>LoadLibraryA <\/strong>?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I was preparing last dirtyJOE update I&#8217;ve noticed that under some circumstances python DLLs are not freed from memory. What was even more interesting, this behaviour was occurring only in ready to release version of application. I&#8217;ve tested few scenarios and I figured out that the problem lays in UPX loader. I&#8217;ll try to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,3],"tags":[],"_links":{"self":[{"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts\/80"}],"collection":[{"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=80"}],"version-history":[{"count":24,"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts\/80\/revisions"}],"predecessor-version":[{"id":677,"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts\/80\/revisions\/677"}],"wp:attachment":[{"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.rewolf.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}