Title: Bug results in crash when loading some DLLs. (with code fix!) · Issue #101 · fancycode/MemoryModule · GitHub
Open Graph Title: Bug results in crash when loading some DLLs. (with code fix!) · Issue #101 · fancycode/MemoryModule
X Title: Bug results in crash when loading some DLLs. (with code fix!) · Issue #101 · fancycode/MemoryModule
Description: I tried to load a DLL which is protected with WinLicense into a process. When calling the entry point I got a crash when Data Execution Prevention was enabled for the process. I analyzed the problem and found that fancycode has a fat bug...
Open Graph Description: I tried to load a DLL which is protected with WinLicense into a process. When calling the entry point I got a crash when Data Execution Prevention was enabled for the process. I analyzed the proble...
X Description: I tried to load a DLL which is protected with WinLicense into a process. When calling the entry point I got a crash when Data Execution Prevention was enabled for the process. I analyzed the proble...
Opengraph URL: https://github.com/fancycode/MemoryModule/issues/101
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Bug results in crash when loading some DLLs. (with code fix!)","articleBody":"I tried to load a DLL which is protected with WinLicense into a process.\r\nWhen calling the entry point I got a crash when Data Execution Prevention was enabled for the process.\r\nI analyzed the problem and found that fancycode has a fat bug which has not yet been reported here.\r\nThese bugs are not relevant when you load a \"normal\" DLL.\r\nBut a DLL which is protected with WinLicense has strong anti-debugging techniques built in.\r\nWinLicense modifies the executing code at runtime!\r\nIt permanently writes into the code section.\r\n\r\nApart from that I found fancycode (written by Joachim Bauch) is very clumsy and awkward.\r\nThere is lot of code which is superfluous and far more complicated than necessary.\r\n\r\nFor example in CopySections() he calls\r\nmemset(dest, 0, section_size);\r\nThis is nonsense because VirtualAlloc() already returns memory which is zeroed.\r\n\r\nIt is also nonsense that he calls VirtualAlloc() first for the entire image of the DLL (in MemoryLoadLibraryEx()) and then he calls VirtualAlloc() again for each section in CopySections() although the memory is already allocated.\r\n\r\nIt is also unnecessary to call VirtualFree() in FinalizeSection() in the case that a section has the flag IMAGE_SCN_MEM_DISCARDABLE.\r\nI studied how the Microsoft's LoadLibrary() works and it does NOT free sections which are marked as discardable.\r\n\r\nBut the real fat bug is in FinalizeSections()\r\nWhen he sets the protection flags in FinalizeSection() he passes the wrong size.\r\nThis results in the crash in my WinLicense protected DLL if DEP is enabled.\r\n\r\nCorrect would be:\r\nVirtualProtect(..., Section-\u003eMisc.VirtualSize, ...)\r\nBut he uses instead\r\nVirtualProtect(..., GetRealSectionSize(), ...)\r\n\r\nThis is wrong because the entire section must have the Execute flag, not only the first part where he has copied to with memcpy().\r\nIt is wrong because there are DLLs which unpack or modify code at runtime.\r\nIf the pages where the code is copied to do not have the Execute flag set, Data Execution Prevention triggers an Access Violation.\r\n\r\n\r\nI don't post a pull request because nobody cares here since years.\r\nThis is a dead project. Joachim Bauch neither merges pull requests nor does he answer emails.\r\nSo if you are interested take my code and fix it on your own.\r\n\r\n\r\n```\r\n\r\n// Copy all sections from file data (pu8_Data) to virtual address in memory\r\n// Returns API error\r\nDWORD CopySections(const BYTE* pu8_Data, DWORD u32_Size, MEMORYMODULE* pk_ModData)\r\n{\r\n IMAGE_SECTION_HEADER* pk_Section = IMAGE_FIRST_SECTION(pk_ModData-\u003eheaders); \r\n for (int i=0; i\u003cpk_ModData-\u003eheaders-\u003eFileHeader.NumberOfSections; i++, pk_Section++)\r\n {\r\n size_t u32_SectSizeAligned = AlignValueUp(pk_Section-\u003eMisc.VirtualSize, pk_ModData-\u003epageSize);\r\n\r\n if (u32_Size \u003c pk_Section-\u003ePointerToRawData + pk_Section-\u003eSizeOfRawData ||\r\n pk_Section-\u003eSizeOfRawData \u003e u32_SectSizeAligned)\r\n return ERROR_BAD_EXE_FORMAT;\r\n\r\n BYTE* pu8_Dest = pk_ModData-\u003ecodeBase + pk_Section-\u003eVirtualAddress;\r\n memcpy(pu8_Dest, pu8_Data + pk_Section-\u003ePointerToRawData, pk_Section-\u003eSizeOfRawData);\r\n }\r\n return 0;\r\n}\r\n\r\n// Loop through all sections and set the access flags (Read, Write, Execute,...)\r\n// Returns API error\r\nDWORD FinalizeSections(MEMORYMODULE* pk_ModData)\r\n{\r\n IMAGE_SECTION_HEADER* pk_Section = IMAGE_FIRST_SECTION(pk_ModData-\u003eheaders);\r\n for (int i=0; i\u003cpk_ModData-\u003eheaders-\u003eFileHeader.NumberOfSections; i++, pk_Section++) \r\n {\r\n DWORD u32_Size = pk_Section-\u003eMisc.VirtualSize;\r\n if (u32_Size == 0) \r\n continue;\r\n\r\n BOOL b_Executable = (pk_Section-\u003eCharacteristics \u0026 IMAGE_SCN_MEM_EXECUTE) != 0;\r\n BOOL b_Readable = (pk_Section-\u003eCharacteristics \u0026 IMAGE_SCN_MEM_READ) != 0;\r\n BOOL b_Writeable = (pk_Section-\u003eCharacteristics \u0026 IMAGE_SCN_MEM_WRITE) != 0;\r\n if (pk_Section-\u003eCharacteristics \u0026 IMAGE_SCN_CNT_CODE)\r\n { \r\n b_Executable = TRUE; \r\n b_Readable = TRUE; \r\n }\r\n\r\n DWORD u32_Protect = ProtectionFlags[b_Executable][b_Readable][b_Writeable];\r\n if (pk_Section-\u003eCharacteristics \u0026 IMAGE_SCN_MEM_NOT_CACHED) \r\n u32_Protect |= PAGE_NOCACHE;\r\n\r\n BYTE* pu8_Address = pk_ModData-\u003ecodeBase + pk_Section-\u003eVirtualAddress;\r\n\r\n DWORD u32_OldProtect;\r\n if (!gf_VirtualProtect(pu8_Address, u32_Size, u32_Protect, \u0026u32_OldProtect))\r\n return GetLastError();\r\n }\r\n return 0;\r\n}\r\n\r\n```\r\nThe following clumsy functions and structures are not needed anymore:\r\n\r\n```\r\ndelete: GetRealSectionSize()\r\ndelete: FinalizeSection() // do not confuse with FinalizeSections()\r\ndelete: SECTIONFINALIZEDATA\r\n```\r\n\r\nAs you see my functions are far shorter than the original code.\r\nAnd they work without crash!\r\n\r\nAlso have a look at my further postings here:\r\n\r\nCreate Activation Context Implementation (important)\r\nhttps://github.com/fancycode/MemoryModule/issues/100\r\n\r\nRemove unneccessay functions for searching resources:\r\nhttps://github.com/fancycode/MemoryModule/pull/53#issuecomment-647021817\r\n\r\nand more...\r\n\r\nBy the way: The code from Joachim Bauch is not cleanly written.\r\nYou find a much cleaner code to load a DLL to memory on Codeproject:\r\nhttps://www.codeproject.com/Tips/430684/Loading-Win-DLLs-manually-without-LoadLibrary\r\nBut it is lacking support for 64 bit Safe SEH and the Activation Context is not implemented in neither project.","author":{"url":"https://github.com/Elmue","@type":"Person","name":"Elmue"},"datePublished":"2020-07-05T01:28:36.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/101/MemoryModule/issues/101"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:012f7a01-e36e-c38a-b091-d637e4c25ae2 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D6B4:3198BA:2E926A8:3E21D9D:696F18BD |
| html-safe-nonce | 54be6090b409024a268d998b0d54ab45ba1020ce4247fad42e4e3eea78d18bfa |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENkI0OjMxOThCQToyRTkyNkE4OjNFMjFEOUQ6Njk2RjE4QkQiLCJ2aXNpdG9yX2lkIjoiNTQ3MzIxMTM0OTczMjM2NjUyNiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 63af9a40a018c65bb8393c16308e2afa3fd791aaec49d56a6f40979068a6d277 |
| hovercard-subject-tag | issue:650982719 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/fancycode/MemoryModule/101/issue_layout |
| twitter:image | https://opengraph.githubassets.com/e5f3987f82032ddff87579178b03a0912bf818454c7ba2423f45f6a16dfc4007/fancycode/MemoryModule/issues/101 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/e5f3987f82032ddff87579178b03a0912bf818454c7ba2423f45f6a16dfc4007/fancycode/MemoryModule/issues/101 |
| og:image:alt | I tried to load a DLL which is protected with WinLicense into a process. When calling the entry point I got a crash when Data Execution Prevention was enabled for the process. I analyzed the proble... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Elmue |
| hostname | github.com |
| expected-hostname | github.com |
| None | b278ad162d35332b6de714dfb005de04386c4d92df6475522bef910f491a35ee |
| turbo-cache-control | no-preview |
| go-import | github.com/fancycode/MemoryModule git https://github.com/fancycode/MemoryModule.git |
| octolytics-dimension-user_id | 247730 |
| octolytics-dimension-user_login | fancycode |
| octolytics-dimension-repository_id | 1018522 |
| octolytics-dimension-repository_nwo | fancycode/MemoryModule |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1018522 |
| octolytics-dimension-repository_network_root_nwo | fancycode/MemoryModule |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 39aed5006635ab6f45e6b77d23e73b08a00272a3 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width