Hacker News new | past | comments | ask | show | jobs | submit login
Ray tracing in notepad.exe at 30 FPS (kylehalladay.com)
747 points by ingve on May 20, 2020 | hide | past | favorite | 101 comments



I remember doing the "use PostMessage to send a WM_CHAR" trick as part of program I made to auto-draw in a FaceBook drawing app.

It would read a pixel value from a file, then "click" in the FaceBook app's color textfield, send 7 delete messages to remove the #000000 color, type in the new color value, then "click" at an X/Y position. It did it 10 times a second.

It worked great until I accidentally focused another app while it was running: and the 70 delete-messages-per-second got sent to Microsoft Outlook.

It took me a while to figure out what was going on as screenfuls of emails evaporated before my eyes.


In old Japanese internet that kind of bitmap-to-click tools were called “dot-tre” or “dot tracer” after the name of an app in mid 2000s


Well, basically the same story but with Auto Hotkey scripts!


Can get messy real quick!

I have:

  F9::
  Reload
  Return
in all my AutoHotKey scripts, so hitting F9 will cause the script to reload and thereby stop anything running. Also handy when doing edits and you want to reload to test.


Hopefully it wasn't a shift+delete message!

;-)


Hacks like these are fun; but there's a number of interesting takeaways from something like this. One is that applications supporting accessibility or scripting interfaces are really, really important: they let other apps interact with your program in ways you may have never imagined, "for free".

Another is that platforms have been locking down on cross-application access for quite a while, for security reasons. Reading or writing a process's memory is a big no-no these days, since it effectively lets you inherit the privileges of that application, and some operating systems will prevent you from doing it altogether no matter how much privileges you have. The latter operating systems have also begin to lock down the APIs that give programmatic control as well, which is somewhat sad…

Finally, when doing things like this try to see if you can find the "highest level" to do such hackery at. Ideally, the app has functionality built-in to do what you want, and if that doesn't work see if the accessibility APIs can help. Then see if you can find functions in the binary to call, and then as a last resort you can touch data structures in memory. This is because using higher-level APIs is more likely to keep things working: you might be changing the string in memory, but some code at a "higher level" might not expect that and misbehave. Perhaps it cached the string's length or thinks it has exclusive access to that memory so it overwrites your modifications. Have fun with your hacks, but be careful!


The Valorant hack through Raspberry Pi emulated mouse* that has been going around really shows that while you're right, ultimately those kind of things are like DRM in that they fight a fight that they cannot win by design.

You can't stop the user (or other application pretending to be him) from accessing the content of something while allowing him to access the content of something, and you can't stop the user (or other application pretending to be him) from interacting with your software while being interactive for him.

* actual mouse is plugged into the pi, pi is plugged in the computer in usb and pretend to be a mouse, video output is piped into the pi, software magic running on the pi "fix" the mouse movement to make perfect aim when need be through image analysis https://www.youtube.com/watch?v=d1jz8qbzfIk


There were also mice you could buy which were programmed to undo the recoil pattern of guns in a game. The game responded by blocking the usb ID of those mice. But there is nothing stopping them as showing up as another brand of mice.


do you have more details on that? I haven't been gaming for a while but you got me interested about the setup and how it works


I am so glad this demo exists, because it identifies one of the many great things that modern sandbox security is trying to destroy

I had a lot of fun as a kid fucking with Windows in Spy++. Oh your shareware program disabled the "Continue" button?? Let me just go in there and reenable it. It was like the DOM inspector but for Windows itself.

Later I got to use these skills to port a Firefox addon to Internet Explorer. It was a contraption, and it worked. Ironically that project died because I couldn't get the installer to work right


You dont want coolgame app to be able to read and alter sucurebank app. the funny thing with for example snap apps is that most want full privileges...


Doesn’t Windows require Administrative privileges to access another process’ memory? I know it does to get direct access to a hard drive. Granted, it would be nice if one had to explicitly whitelist an app that wanted to read other process’ memory.


You don't need admin to do it to yourself, otherwise debuggers wouldn't work. It will fail if you do it for an unrelated user though.

Basically the permissions are enforced at OpenProcess(), and these are the permissions you can ask for: https://docs.microsoft.com/en-us/windows/win32/procthread/pr...


Up until recently it was standard to just blindly grant admin to whatever asked for it, because UAC's implementation was so damn naggy. With Windows XP or before there was no UAC and most everyone ran as admin unless you were computer savvy or on a corporate PC.


Many years ago this was brought up as a security issue with Windows that was "impossible" to fix, can't remember what they called it though.


Feature


Could one run a snap application in a chroot inside a VM in another city via ssh work for better security ?


I'll take security over cool tech demos. And you still can do these things. Just run your demo as root or turn off the security features.


But it's more than just cool tech demos. You could add features to Windows itself, with first-class integrations that looked and felt as if it was shipped by Microsoft. You could automate things that didn't have an automation interface, and you could extend software that couldn't otherwise or didn't want to be extended. Your computer was truly yours.

Sure letting it be a free-for-all was a bad idea. I'm fine with granular permissions, but am wary because it means I'm relying on features that upstream could turn off because they felt like it, or it made them look bad, or it introduces a security hole they just don't want to fix.

It's giving away liberty for security.


I guess you do lose something as a windows user but this kind of hack was always pretty crappy and has a much better alternative. As a linux user I am used to everything having both a gui, cli and often language libraries. Writing a script for cli commands is much much nicer than hacking some gui. And much less likely to break.


I grew up delving through the Windows labyrinth. Now I am comfortable at a command line and can write a mean bash script, but initially I abhorred it :)


I did some windows hooking/hijacking years ago when I was working on a poker bot, and found that I couldn't get access to some text output of the poker client.

Fun fact. The C++ hooking library I found, Detours, which at the time was the most common (only?) library for hooking windows API calls. It was written by microsoft research for accessibility reasons. There are 2 windows API functions (maybe more) that will render text to the screen basically as a bmp making it impossible to gain access to the text being written. Not sure if this was an oversight by the MS windows group, or it was intentional to allow for developers to obfuscate text output in various ways. Thing is, this breaks screen readers. So microsoft got to create a library that unbreaks their API, which I personally found very amusing at the time.

Also you should know, that the library makes it obvious it's being used if the client has enough privileges. I don't remember the details because I never needed to care. But it's some combination of adding a process in task manager, and making an obvious fingerprint in memory. I think this was to appease complaints of use by more nefarious purposes than screen readers. My understanding is that companies like Blizzard know how to find you're using detours, if you don't go out of your way to modify the library before compiling it.

https://www.microsoft.com/en-us/research/project/detours/


This is only tangentially related to your post, but it appears as though Detours is open-source!

https://github.com/microsoft/detours


I'm a radiology resident. I did a similar thing with PowerScribe 360, the most popular dictation tool for radiologists. I injected an auto-complete dropdown and an inline spell checker. The Win32 SendMessage APIs are quite powerful if the underlying program is built on top of Win32.


Only problem is that a lot of apps are being run “in the cloud” over Citrix these days. Suddenly all you have is a streaming image.

Sometimes you can work with the x and y coordinates if you resize each screen each time.

Sometimes that can be very fast because you can click on the controls before they’re even drawn on your screen.


Citrix often works so poor that _I_ click controls of program I use often before they are drawn.


PostMessage not SendMessage. Latter waits, former doesn't hence why you can end-up with a hang if you mix one with the other. On other hand, if you want sync communication you use SendMessage.


I'm less interested in how he got Notepad in particular to do this and more interested in how convincingly he managed to represent a 3D object by projecting it onto a grid of ASCII characters. I've seen plenty of ASCII art, but I've never even considered what it might look like animated.

I went looking for something similar that was interactive and found ASCIICKER. It's everything I wanted and more.

https://asciicker.com/y6/


Whoa, Nelly. I just freaked out after hitting q and e to rotate. I thought it was just a 2d representation and ... it's not. Thanks for finding this.


You can see the developer's progress in the previous versions, eg https://asciicker.com/x8/

There are a whole bunch linked on the main page: https://asciicker.com/


There is also libcaca: http://caca.zoy.org/wiki/libcaca

I remember seeing Chromium Embedded Framework had a caca backend (circa 2015) so you could use the chromium renderer in a text terminal.


It's funny how CheatEngine seems to see a lot of use as a legit "professional" dev tool. I personally don't use it because I don't run Windows a whole lot but I've had a few bug reports on github where people would use CheatEngine to investigate bugs even though the code was fully available so you could use any full-featured debugger instead.

I suspect that some younger developers simply started tinkering with CheatEngine before they learned proper programming so they feel very comfortable using it instead of a regular debugger. I started programming by tinkering with BASIC game listings so I feel a certain kinship with this approach.

Also CheatEngine is probably easier to set up and will work regardless of whether you have access to the source or not. And unlike more advanced tools like IDA you don't have to worry about expensive license or pirating since it's free and open source.

That being said if you're reporting bugs on open source projects on GH please try to use more appropriate debugging tools, I don't know what to do when somebody starts posting dumps of the Windows VM address space to show me how something isn't working as it should...


In terms of simply poking around with memory cheatengine's UI is much more direct than (say) GDB or similar


Yeah, you could consider going to something like x64dbg for this case, but really for finding data in memory, CheatEngine is king.


It really says a lot that kids are so easily able to use/understand what is going on with Cheat Engine, despite how powerful it is.


Tells you that people with a goal to accomplish don't need to have their tools dumbed down for them, despite what modern UX trends would have you believe.


GDB is an absolute nightmare to use with Asm, it's almost like it was designed to discourage it. Look up the absolutely perplexing behaviour of the "disassemble" command[1] for one example --- the first time I encountered it, I exclaimed "WTF!?" out loud.

WinDbg, and DOS's DEBUG that came before it, feel far more natural with such (and the former can also debug at source-level.)

[1] "No function contains specified address." -- when there is absolutely no requirement for anything to resemble a function in order to be capable of being disassembled.


Hit a breakpoint? My fingers are already typing x/10i. LLDB does stupid things otherwise as well (I think it will automatically "move your cursor down"?) so this is just the command I always reach for.


Yeah by default gdb sucks a bit for assembly, fortunately it's easily scriptable so I have a file with a bunch of functions to make it behave a bit more reasonably.


If you're on Mac, I remember using Bit Slicer with great success sometime last year for similar purposes and intent (easy GUI to poke around in memory.)


I'm happy as the author that it's still seeing some good use :)


I love how useless this is. Hacking for the sake of hacking. Really cool!


It’s not possible to read data in a different process’ address space directly (or at least, I didn’t stumble on how to do it). Instead, I first needed to copy the contents of a page range to the memory scanner’s address space.

How about injecting your code into that process? (Either from your own DLL via LoadLibrary and SetWindowsHookEx; or WriteProcessMemory directly into it then CreateRemoteThread) [1]

I love that Windows lets you do this kind of stuff. Security nightmare, sure, but it allows use cases the creators couldn't envision (e.g. I believe UltraMon uses it to add and override window functionality). The first time I injected a hook into another app from Visual Basic it felt like I had a new superpower.

I was going to add some code to force notepad to use the fonts I wanted (Consolas, 11pt), but for some reason sending WM_SETFONT messages kept messing up how fonts were displaying

For this one you could automate the menu dialogs to display the current font. SendKeys should do the trick, then read the control values with the same methodology already used in your project.

[1] https://www.codeproject.com/Articles/4610/Three-Ways-to-Inje...


Someone use that technique to hook a WSL bash shell in there. I can't wait for notepad to be my terminal.


Do it!


Actually. I just added something similar to my emacs yesterday:

    (defun sh-line ()
      (interactive)
      (let ((cmd (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
        (end-of-line)
        (newline)
        (insert (shell-command-to-string cmd))))
    (local-set-key (kbd "M-RET") 'sh-line)
With this Alt-RET will evaluate the last line in your shell, and insert the output.


It is worth mentioning that Emacs is a wee bit easier to script than notepad.exe :)


Speaking of Emacs, shells and WSL, I recently had to shell out from Emacs under WSL to git-bash under Windows proper, to run cmake to run MSBuild, and get the generation/compilation output all the way back. Turns out, while regular M-x shell-command would work, M-x async-shell-command (i.e. shell-command with appended &) would not - it wasn't able to communicate with the spawned process. I needed it to be async so that a compile wouldn't block my Emacs.

The solution I came up with is a bit lower-level, looks like this:

  (make-process :name "some_name"
                :buffer "buffer"
                :command ("cmd" "to" "run")
                :connection-type 'pipe
                :coding 'utf-8-dos)
Two key lines are :connection-type 'pipe, which solves the I/O issues, and :coding 'utf-8-dos, which ensures the output streamed to an Emacs buffer isn't polluted by ^M (CR from CRLF line ending).

Now, if anyone figured out how to configure a connection to a language server across the WSL boundary, I'm all ears.


Does `M-x compile` not work for you on windows? This is what I use to do run build scripts async.


Thank you! Macintosh MPW had a very similar feature back in the day, it rocked. Haven't seen it since. Added to my .emacs!


I once used the similar strategy to hook into DC++ used for lan file sharing in our school. There was a chatroom game which had contest for unjumbling jumbled words. My app would inject into the DC++ messaging pipeline, read the unjumbled word and type back the correct answers.

It infuriated long time players whose score I beat in just a few days. It was fun :)

Still have the source code here - https://github.com/shadabahmed/quizroom_hacker


I never got to program for classic Mac OS, but I wonder what a similar program would look like, considering they didn't have memory protection or anything.


A lot of cool hacks where possible because of that.

One very useful, was an extension that allowed you to “save” a file even after you‘ve hit “don’t save”


Oh, Mac OS had oodles of these. Even Mac OS X had a bunch of "Haxies" because it would load plugins into every process for a while. These days you need to turn off a bunch of security features to make it work in general.


How common is it to be able to read/write another program’s memory space? It’s not something I’ve ever done before, but it doesn’t seem like it’s a very good idea from a security standpoint. Are there other use cases that I’m missing?

Still, this is a really cool hack.


This is a great example of how security has changed from the applications being installed by the system administrator being "trusted" and access control focused on users, to the main threat being malicious applications all nominally under the control of the user but with unwanted behaviour.

Directly going into another process's memory is a bit antisocial and unreliable, so it's normally only seen in debuggers and cheat engines. Some systems use shared memory deliberately to communicate, but that's setup specially (MAP_SHARED etc).

What's far more common is shared code "injection": Windows shell extensions, for example. Keyboards and input method helpers. Or OS hook mechanisms: Autohotkey. COM/OLE. And if you want to be baffled and terrified, "OLE Automation" which lets you RPC into Microsoft Word.

I tried searching for detailed explanations and came across this absolute horror: https://supportline.microfocus.com/documentation/books/nx30b... (how to use ActiveX from Object COBOL)


Just wanted to point out screen readers and other disability tools are a very important reason to read and modify another application memory. My understanding is this was a primary motivator for the detours library. Though I can't seem to find the MS Research blog post talking about this nearly 20 years ago, I'm wondering if there's some revisionist history that's happened :(


Screen readers should not require reading (or modifying!!) a process's memory; platform UI toolkits make this information available programmatically.


Except when they don't, or don't give enough context. A top-level comment here[0] gives an example where text was internally rendered to a bitmap prior to display, so a MS library was needed to hook the relevant API calls to get at the source text. Unfortunately (in this exceptional case), native UI toolkits aren't always as nice as webpage DOM. We'll probably start experiencing the same issue on the Web as soon as WebAssembly gets popular enough for people to develop UI toolkits on top of it.

--

[0] - https://news.ycombinator.com/item?id=23251509


I should have probably said "good platform UI toolkits" :P


> screen readers and other disability tools are a very important reason to read and modify another application memory.

That has historically been true on Windows, and to the extent that people still need to use legacy applications that use GDI (the Win32 graphics API), it sometimes helps to use a screen reader that uses such hacks. But for applications using any modern graphics stack, we must rely on programmatic accessibility APIs like UI Automation.

I have some expertise in this area. I started developing a Windows screen reader in late 2004 (for a tiny company, long before I joined the Windows accessibility team at Microsoft). Naturally I started with the proper programmatic accessibility API at the time, Microsoft Active Accessibility (MSAA). I quickly encountered MSAA's severe limitations and had to turn to other techniques, such as sending window messages to Win32 edit controls to get the text under the cursor or the current selection. Internet Explorer and the Office apps had COM-based object models, so I used those as well.

About a month into developing my screen reader, I realized I was going to need something more. I kept running into pieces of UI that I couldn't access through MSAA, window messages, or an object model. I came across a technique called API hooking, that is, patching user-space Windows API functions in memory at runtime, and I realized that I could do this with GDI functions. I knew that other Windows screen readers -- all of the serious ones -- hooked into GDI, but they did it in kernel space, by installing a fake graphics driver that would receive all the function calls from the GDI subsystem in the kernel, pass the information to the screen reader, then forward the calls to the real graphics driver. I figured that with API hooking, I could do something like that in user space. Note that I didn't do the low-level patching (i.e. rewriting x86 instructions) myself; I found a cheap commercial library that did that part. But I wrote the code to apply the technique to the specialized domain of screen reading.

I should mention that I was late to the screen reader game. The real pioneers started releasing Windows screen readers in the early 90s. And one of those pioneers came up with a term for what we were doing, which became common across the industry. They called it an off-screen model. It basically worked like this: a screen reader would hook GDI functions like TextOut, FillRect, BitBlt, etc., and use the information gathered from those function calls, as well as whatever state it could query from the GDI device context, to build a model of what was on the screen. For each piece of text, the model would have information like the text string itself, the bounding rectangle, the color, the width of each character, the font name, the font weight, and probably some other things I've forgotten (I wrote most of that code in 2005 and haven't worked with it in a long time). Whenever a rectangle was filled (e.g. through FillRect or ExtTextOut), we'd note the color, so we could use it for things like detecting whether a given piece of text was highlighted and should be spoken automatically. And we had to keep track of which GDI bitmaps represented graphics, and which ones were text that had been drawn into off-screen memory and then blitted onto the screen. In short, it got really complicated. But it was the only way we could provide access to some important applications.

There were limits to what we could do with this kind of hooking and hacking, though. In early 2006, I heard that TurboTax wasn't accessible with any screen reader. Full of the hubris that comes from having some success at something difficult (edit: and being young), I bought a copy of TurboTax (though I had no intention of using it), installed it, and jumped in to see how I could make it work with the product I had been developing. I quickly discovered why none of the other screen reader developers had been able to make it work. I've long since forgotten the details, but the problem was something like this: Instead of drawing text into a GDI bitmap and then using BitBlt (or one of the similar functions) to blit the bitmap onto the screen, TurboTax would draw into a GDI bitmap, transfer the contents of that bitmap into normal memory, and then somehow blit from that memory onto the screen. Because of this roundabout approach, a screen reader's off-screen model lost track of the bitmap, and by the end, saw it as nothing but an opaque image.

So, off-screen models were fragile even with the fairly simple GDI. I don't think any screen reader developer ever shipped an off-screen model that worked with more complex graphics APIs like DirectX or OpenGL. By the time major non-gaming applications on Windows started replacing GDI, about 10 years ago, it was clear that programmatic accessibility APIs like UI Automation would be the only reliable solution going forward. And now, as a developer on the Windows accessibility team at Microsoft, I work on the Narrator screen reader, which relies exclusively on UI Automation. Sometimes I miss the ability that I had to hack accessibility into an application that wasn't accessible by design; it felt like a superpower. But I know that the days of being able to do that are over, for many good reasons.


Indeed, we are slowly heading toward that authoritarian dystopia envisioned by Stallman over 20 years ago:

https://www.gnu.org/philosophy/right-to-read.en.html

In 2047, Frank was in prison, not for pirate reading, but for possessing a debugger.


Oh yeah I remember <pretty big accounting app> which used OLE hacks to use word, excel and access as a backend


CheatEngine needs Root / UAC admin.

If you are root, you can do almost anything on your OS, including reading/writing another program memory space.

I guess a common usecase is when debugging an executable.

Read/write another program’s memory space is commonly used in video games hacks but nowadays they are doing it using drivers to access the Ring 0 (Kernel Mode) and have full control over the OS and bypass user-mode anti-cheats.


In normal operation, very uncommon. Many protections to prevent it from happening in the normal, day-to-day activity.

However, in diagnostics it is extremely common, because it's how debuggers and a ton of other necessary tools work. Debuggers go in even more deeply than that, they can pause execution and single step it, etc. So it's hard to remove the things these tools use to work.

Beyond that, Windows has its own weird concerns here. At the very bottom layer of the way Windows was designed, all windows were in a common space on a single-user system (think Windows 3.0 era here), and all windows can send arbitrary messages to each other, and those messages are often very powerful commands. Not quite literally "set this memory value to that", but things like "set text to this" or "redraw yourself" or "terminate yourself", plus any additional arbitrary things the programs added for their own message loop internally. While Windows has had the basic process model protections of not allowing direct memory access to other process, etc., historically speaking being able to send Windows messages to arbitrary processes has any number of ways of escalating to code execution, even before we get into buffer overflows and such (though there were plenty of those). It has been a long and bumpy road securing Windows against all of these issues to make it multi-user safe. While this particular hack doesn't use windows messages to do all of the work, note that there can still be some legitimate surprise at how much access a program can get to Notepad just by sending messages, like, directly telling it to run its rendering loop to redraw its screen.


Debugers have been already mentioned, but antiviruses do that, as well as various cheat and anti-cheat engines.

From a security perspective, reading/writing another program's memory space is well understood as a specific, risky privilege, so in all modern OSes control and prevent that if it's not "your" process or unless you're root/admin already.

But a cool thing for reading/writing another program's memory space is the ability to do that through PCI without the OS being able to intervene - e.g. Ulf Frisk's PCILeech (https://github.com/ufrisk/pcileech/), here's a video demo of writing to Notepad's memory remotely https://youtu.be/5DbQr3Zo-XY?t=1440


If I remember correctly, not long ago someone posted here about a cheat using DMA to modify the display buffer of a shooter. I'm in a hurry but I'll look it up later.


Well, with DMA, one can do pretty much anything. Doesn’t Thunderbolt (which is PCIe and hence has DMA) have this problem? As in, couldn’t a rouge TB peripheral siphon your data?


Thunderbolt & Firewire before it. DMA to external devices is powerful but the feature also means you expose a bus that wasn't originally conceived to be read by malicious agents.


Some operating systems do not allow you to do this even if you are root.


Well shared memory is a non-adversarial and limited way to effectively read and write the memory of an other process.

It doesn't have any obvious implications security-wise since obviously if a process can read and write an other processe's memory then obviously you have some amount of trust that it's not going to do that. That's why you generally need certain privileges to do that.

The main problem is that messing with a process memory is inherently non-portable and very likely to break if the program changes even slightly. Actually if the system uses address space randomization it may even change between invocations of the program. As such the only programs that usually bother to do that are debuggers and tracers.

Before the advent of MMUs and virtual memory everybody shared the same address space and everybody could write everywhere. Fun times. You still have MMU-less system nowadays but it's generally limited to really low power (or really old) microcontrollers.


I'd not call it common.

Back in the days of old (windows 3.1), I did that to extract dictionary entries - had to control the interface with wm_click too. There was way more encoding than notepad shown in the example, end result was rft. The basic principle is that it was possible to make the process load a DLL.


Debuggers.


There we go... that was the obvious use case I was forgetting!


I have used it for testing running release programs.


That's awesome! An example of true art in software engineering! Kudos!


As soon as I saw: "Sending Key Events To Notepad" I simply thought AutoIt and moved on.

There is no denying how cool the end result is but input to any Windows thingie can be scripted with AutoIt in a nice easy way with a very expressive, BASIC style language that has existed for decades. You can get it to churn out a self contained .exe.

I don't know why Windows sysadmins piss around with anything less for most tasks on an OS that needs a GUI. You can always call into or out of PS/cmd or whatever as needed.


Would it be efficient enough to render a rotating cube at 30fps?


No. I doubt it will be even 1 FPS.


Tools for the job


And that is exactly my point.


this is a great introduction to programming on Windows


Reminds me of stuff like "Advanced Windows 95 Programming" by Jeffrey Richter


IIRC you can just use WM_SETTEXT message instead. Don't know about FPS, probably in between of the two methods you used.


I'm not sure this would work. The "game" is running in a different process than notepad and WM_SETTEXT accepts a memory pointer as input. This pointer would be meaningless because it's coming from a different process.


Windows does automatic parameter marshaling for system messages (0 to WM_USER-1), which WM_SETTEXT is a part of. Since the meaning of the parameters is well-established, the system can allocate memory in the target process and replace the pointers with meaningful values for the target wndproc.


You can also allocate memory on the hooked process, Notepad in this case, and modify that one then use WM_SETTEXT. I thought about that when I saw his "wait to fill Notepad with WM_CHAR" which took like 10 seconds? Anyway WM_SETTEXT would be faster then 30 FPS he achieved with accessing Notepad's buffer memory since he's doing a lot of extra-work there to achieve the final result.


I never heard about cheat engine before. Are there similar tools for other platforms? I know you can hook GDB to any running process, but once you're in the process, discovering what is occurring is often pretty difficult.

I'm guessing this is how a lot of the game shark cheats were discovered back in the day.


for linux there is scanmem and it's gui gameconqueror, which offer the same core functionality of memory scanning

https://github.com/scanmem/scanmem


This tweet mentions a trick which uses Notepad as a logging sink. https://twitter.com/steveklabnik/status/1263190719721766918



Here is a Serilog sink for .NET apps that writes directly to the most recent Notepad window opened by the user https://github.com/augustoproiete/serilog-sinks-notepad


That post could have been a lot shorter had they known about UI Automation. Not sure whether it's far enough, but it definitely would have tried that probably before even using WM_CHAR, simply because you can just tell the text box to adopt a new text.


This is severely cool. Human endeavour never ceases to amaze me. For me, the most beautiful aspect of being human is the length people go to, to express themselves through their creations.


It seems like the refresh rate of Notepad itself is lower, as one can see half-drawn frames in the GIF. But a really cool experiment nonetheless.


Caused by the separate background redraw pass of Win32.


I've got a script somewhere that auto saves notepad. I sometimes wonder if it's marketable


This must be mentioned somewhere in the Book of Revelation, surely.


This is the stuff that keeps me on my toes, thank you bro


Stuff like this is why I love HN :)


Nice work!. Thanks for sharing




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: