57 ms·
As someone who has only ever written about 20 instructions worth of assembly, I am kind of torn. The kind of cleverness needed to thwart the decompiler's effor
by krylon 9y ago
As someone who has only ever written about 20 instructions worth of assembly, I am kind of torn.
The kind of cleverness needed to thwart the decompiler's efforts is very impressive. A part of me wishes I had been around at a time when assembly was an acceptable "language" instead of the last resort it is today for most scenarios. Getting this close to the metal (or silicon) and being able to pull off such a stunt must be exhilarating.
At the same time, another part of me is very happy I do not have to deal with such low-level details. Debugging code written in assembly (with assembly being the main language, not just inline assembly in a C/C++ program or something like that) must have been exquisite torture.
- nether 9y agoI agree, this is pretty leet. Too leet for me.
- jackhack 9y agoDebugging was just different. You had to get into the mindset of the original developer and understand what he intended and the impact of poking a memory-mapped location (could cause a graphics page flip, or toggle the speaker, or executing something in ROM). Comments were your friend. Without, yes, it could be a challenge. But decompiling & debugging wasn't just limited to ASM. I once worked for a shop that lost its original C source code and only had a copy of the executable. (major source code control failure - no backups of the server). They decompiled it and worked from the resultant C code. It was as bad as you can imagine, and enormous amounts of time were spent renaming "variable1" to "customerName", or methods from "sub232" to "CalculateTax()", etc. After a few months the code was sprinkled with meaningful names, but it was still very difficult to read and felt very unnatural, formal, and distorted. It also ran slower than the original when recompiled. But as for defeating a disassembler, I recall a few strategies stretching back to the late 70s/early 1980s on the Apple ][, when the "disassembler" was a human being rather than a tool. This is probably more appropriately called obfuscation or even copy protection, but it feels related. There were a variety of approaches taken: * Self-modifying code. This was the most common approach. Code would loop through areas of memory, incrementing/decrementing values by set values or based on an algorithm to produce valid opcodes. At any point in time, much of the code loaded was nonsense, so debugging had to be done in decoded blocks. * Jump tables (and indexed jump tables with offsets calculated at runtime) so that the code would skip all over the place. This was mostly just an irritation, rather than a hard obfuscation. * Burying executable code in resources (sounds/images) and related techniques such as code that calculated its hashvalue and used that to self-modify to 'unlock' executable blocks. *Overlays. Code was loaded on top of unused resources, and resources loaded on top of code. And while it wasn't a decompiler defeat, per se, changing the timing for the floppy disk drivers which read from non-standard disks would prevent one from simply loading data from disk and decompiling -- only that code that is in memory could be examined. Nybble-copiers were created to defeat this approach. One or all of these approaches could be combined to produce code that was a nightmare to debug, but ultimately anything that the computer could execute could be decompiled, eventually. Fun times.
- js2 9y agoFor the Apple ][ there was even a card (the “wildcard”) which would interrupt the CPU and dump the memory to disk along with a special loader, allowing you to reboot from the disk and resume where the CPU left off. I don't think it had any valid use besides defeating copy protection: http://mith.umd.edu/vintage-computers/items/show/11 http://mith.umd.edu/vintage-computers/items/show/11 Oh and I just found this thing called the “Senior PROM” which I’d never heard of before: http://planemo.org/retro/senior-prom-reverse-engineering/ http://planemo.org/retro/senior-prom-reverse-engineering/ Here's some examples of early copy protection techniques: http://www.fadden.com/apple2/cassette-protect.html http://www.fadden.com/apple2/cassette-protect.html
- tekromancr 9y agoThere is a great collection on the internet archive where someone has gone through and unprotected tons of apple][ disks and documented the copy protection. It's pretty good reading, but a little repetitive after a while. https://archive.org/details/apple_ii_library_4am&tab=about https://archive.org/details/apple_ii_library_4am&tab=about
- pjmlp 9y agoIt was different. Being able to use hardware tricks for programming, like non-standard display modes, self-modifying code, or fit a few more bytes into 64 KB was worthy of geek brownie points, specially at demoscene parties.
- Someone 9y agoOne can also claim that today’s programming is torture. Back in the microcomputer days, all you needed to write a program was a desk with a single computer, one or two tools that you knew through and through and a few reference books. Nowadays, we sometimes spend days or even weeks choosing our tools and libraries of sometimes questionable quality and getting them to work together before we can even start thinking of the problem we want to solve, and even then, we still spend half our days googling, and being lucky if we get semi decent answers.
- thaumaturgy 9y agoIt's six o' one, half-dozen t'other for me. My most formative years as a programmer mostly involved 68040 assembly on the pre-PowerPC Macs. Back then, I used CodeWarrior a lot, and if there was a head-scratching bug in my software (as there often was), I could launch it from a fully-featured debugger, set breakpoints, skip ahead to a block of code, step through it line by line, see every single value that existed in raw hex on the heap, see exactly what was on the stack. If I was wanting to flip bits in someone else's software, I had MacsBug, which was a stop-the-world OS-level debugger that did all the same, but even better. [1] Back then, there was a very definite sense that I owned the computer, that it was my tool, that it would do precisely and exactly what I wanted it to. In a way, whether something was open source or not didn't matter; I could modify it anyway, and often for less effort than it takes to crawl through a modern over-architected codebase. However, now I can glue some really impressive libraries together, written by other people and available on massive centralized code repositories, and deliver an application to as many people as I want, all running different hardware or operating systems (within reason) but still all getting the same software experience (...mostly...), and even charge some money for it without having to worry about somebody cracking the license check on my shareware. The effort required to make complicated new software has gone way down. The effort required to troubleshoot and fix complicated software has gone way up. Nowadays, when I'm doing the former, I'm happy, and when I'm doing the latter, I'm not. I think that might be part of why there's so much churn in the software industry today. [1]: MacsBug did this in real-time. Start up an application, drop into MacsBug, set a breakpoint on a function call, switch back to the OS and application, trigger the function call, then step through the code in MacsBug. If you were careful, you could even "rewind" code under certain conditions, so you could, say, change a branching opcode, back up, go back to the OS and see if the change did what you want.
- gmiller123456 9y ago>A part of me wishes I had been around at a time when assembly was an acceptable "language"... Probably not as glamorous as you're imagining. It took a long time to get anything done, and most of that time was spent finding bugs. All the time a lot of people thought the real cool people where the ones before who had to program using wires and vacuum tubes. Best advice is, don't try to mimic those of the past, become a master of your own domain and change with the times.