{
	"id": "a4d8430d-fd84-4dcc-8160-42972b368374",
	"created_at": "2026-04-06T00:11:02.773834Z",
	"updated_at": "2026-04-10T03:19:56.427403Z",
	"deleted_at": null,
	"sha1_hash": "363c9d19823c6d0b0de98c327e2f943115511e99",
	"title": "A Quick Solution to an Ugly Reverse Engineering Problem — Möbius Strip Reverse Engineering",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 209006,
	"plain_text": "A Quick Solution to an Ugly Reverse Engineering Problem —\r\nMöbius Strip Reverse Engineering\r\nBy Rolf Rolles\r\nPublished: 2019-01-14 · Archived: 2026-04-05 14:02:21 UTC\r\nTraining Classes\r\nResearch\r\nBlog\r\nContact\r\nSign In\r\nReverse engineering tools tend to be developed against fundamental assumptions, for example, that binaries will\r\nmore or less conform to the standard patterns generated by compilers; that instructions will not jump into other\r\ninstructions; perhaps that symbols are available, etc. As any reverse engineer knows, your day can get worse if the\r\nassumptions are violated. Your tools may work worse than usual, or even stop working entirely. This blog post is\r\nabout one such minor irritation, and the cheap workaround that I used to fix it.\r\nIn particular, the binary I was analyzing -- one function in particular -- made an uncommon use of an ordinary\r\nmalware subterfuge technique, which wound up violating ordinary assumptions about the sizes of functions. In\r\nparticular, malware authors quite often build data that they need -- strings, most commonly -- in a dynamic\r\nfashion, so as to obscure the data from analysts using tools such as \"strings\" or a hex editor. (Malware also\r\ncommonly enciphers its strings somehow, though that is not the feature that I'll focus on in this entry.) As such, we\r\nsee a lot of the following in the function in question.\r\nWhat made this binary's use of the technique unusual was the scale at which it was applied. Typically the\r\ntechnique is used to obscure strings, usually no more than a few tens of bytes apiece. This binary, on the other\r\nhand, used the technique to build two embedded executables, totaling about 16kb in data -- hence, there are about\r\nhttps://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nPage 1 of 6\n\n16,000 writes like the one in the previous figure, each implemented by a 7-byte instruction. The function pictured\r\nabove comprises about 118KB of code -- over 25% of the total size of the binary. The function would have been\r\nlarge even without this extra subterfuge, as it has about 7kb of compiled code apart from the instructions above.\r\nThe Hex-Rays decompilation for this function is about 32,500 lines. The bulk of this comes from two sources:\r\nfirst, the declaration of one stack local variable per written stack byte:\r\nSecond, one assignment statement per write to a stack variable:\r\nTo IDA's credit, it handles this function just fine; there is no noticeable slowdown in using IDA to analyze this\r\nfunction. Hex-Rays, however, has a harder time with it. (I don't necessarily blame Hex-Rays for this; the function\r\nis 118KB, after all, and Hex-Rays has much more work to do than IDA does in dealing with it.) First, I had to alter\r\nthe Hex-Rays decompiler options in order to even decompile the function at all:\r\nhttps://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nPage 2 of 6\n\nAfter making this change, Hex-Rays was very slow in processing the function, maxing out one of my CPU cores\r\nfor about five minutes every time I wound up decompiling it. This is suboptimal for several reasons:\r\nI often use the File-\u003eProduce file-\u003eCreate .c file... menu command more than once while reverse\r\nengineering a particular binary. This function turns every such command into a cigarette break.\r\nSome plugins, such as Referee, are best used in conjunction with the command just mentioned.\r\nWhen using the decompiler on this function in an interactive fashion (such as by renaming variables or\r\nadding comments), the UI becomes slow and unresponsive.\r\nRandomly looking at the cross-references to or from a given function becomes a game of Russian Roulette\r\ninstead of a normally snappy and breezy part of my reverse engineering processes. Decompile the wrong\r\nfunction and you end up having to wait for the decompiler to finish.\r\nhttps://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nPage 3 of 6\n\nThus, it was clear that it was worth 15 minutes of my time to solve this problem. Clearly, the slowdowns all\r\nresulted from the presence of these 16,000 write instructions. I decided to simply get rid of them, with the\r\nfollowing high-level plan:\r\nExtract the two .bin files written onto the stack by the corresponding 112KB of compiled code\r\nPatch those .bin files into the database\r\nReplace the 112KB worth of instructions with one patched call to memcpy()\r\nPatch the function's code to branch over the 112KB worth of stack writes\r\nThe first thing I did was copy and paste the Hex-Rays decompilation of the stack writes into its own text file.\r\nAfter a few quick sanity checks to make sure all the writes took place in order, I used a few regular expression\r\nsearch-and-replace operations and a tiny bit of manual editing to clean the data up into a format that I could use in\r\nPython.\r\nNext, a few more lines of Python to save the data as a binary file:\r\nFrom there, I used IDA's Edit-\u003ePatch program-\u003eAssemble... command to write a small patch into the\r\ncorresponding function:\r\nhttps://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nPage 4 of 6\n\nAfter a bit of fiddling and manual hex-editing the results, my patch was installed:\r\nAnd then I used a two-line IDC script to load the binary files as data in the proper location:\r\nhttps://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nPage 5 of 6\n\nAfterwards, the navigation bar showed that about 31% of the text section had been converted into data:\r\nAnd now the problem is fixed. The function takes approximately two seconds to decompile, more in line with\r\nwhat we'd expect for a 7kb function. Hooray; no more endless waiting, all for the time cost of about three\r\naccidental decompilations of this function.\r\nThis example shows that, if you know your tools well enough to know what causes them problems, that\r\nsometimes you can work your way around them. Always stay curious, experiment, and don't simply settle for a\r\nsuboptimal reverse engineering experience without exploring whether there might be an easier solution.\r\nSource: https://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nhttps://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"ETDA"
	],
	"references": [
		"https://www.msreverseengineering.com/blog/2019/1/14/a-quick-solution-to-an-ugly-reverse-engineering-problem"
	],
	"report_names": [
		"a-quick-solution-to-an-ugly-reverse-engineering-problem"
	],
	"threat_actors": [],
	"ts_created_at": 1775434262,
	"ts_updated_at": 1775791196,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/363c9d19823c6d0b0de98c327e2f943115511e99.pdf",
		"text": "https://archive.orkl.eu/363c9d19823c6d0b0de98c327e2f943115511e99.txt",
		"img": "https://archive.orkl.eu/363c9d19823c6d0b0de98c327e2f943115511e99.jpg"
	}
}