all repos — gemini-redirect @ 69f17cbf52b3d5a22fa674bb38133feacfeab00a

Deploy site
Lonami Exo totufals@hotmail.com
Sun, 21 Feb 2021 15:43:42 +0100
commit

69f17cbf52b3d5a22fa674bb38133feacfeab00a

parent

b07586dbeca672f601a37884c0bf4c998fca2ed7

M blog/atom.xmlblog/atom.xml

@@ -4,18 +4,372 @@ <title>Lonami&#x27;s Site - My Blog</title>

<link href="https://lonami.dev/blog/atom.xml" rel="self" type="application/atom+xml"/> <link href="https://lonami.dev/blog/"/> <generator uri="https://www.getzola.org/">Zola</generator> - <updated>2021-02-16T00:00:00+00:00</updated> + <updated>2021-02-19T00:00:00+00:00</updated> <id>https://lonami.dev/blog/atom.xml</id> <entry xml:lang="en"> + <title>Writing our own Cheat Engine: Unknown initial value</title> + <published>2021-02-19T00:00:00+00:00</published> + <updated>2021-02-19T00:00:00+00:00</updated> + <link href="https://lonami.dev/blog/woce-3/" type="text/html"/> + <id>https://lonami.dev/blog/woce-3/</id> + <content type="html">&lt;p&gt;This is part 3 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt; +&lt;ul&gt; +&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-1&quot;&gt;Part 1: Introduction&lt;&#x2F;a&gt; (start here if you&#x27;re new to the series!)&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;Part 2: Exact Value scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt; +&lt;li&gt;Part 3: Unknown initial value&lt;&#x2F;li&gt; +&lt;&#x2F;ul&gt; +&lt;p&gt;In part 2 we left off with a bit of a cliff-hanger. Our little program is now able to scan for an exact value, remember the couple hundred addresses pointing to said value, and perform subsequent scans to narrow the list of addresses down until we&#x27;re left with a handful of them.&lt;&#x2F;p&gt; +&lt;p&gt;However, it is not always the case that you have an exact value to work with. The best you can do in these cases is guess what the software might be storing. For example, it could be a floating point for your current movement speed in a game, or an integer for your current health.&lt;&#x2F;p&gt; +&lt;p&gt;The problem with this is that there are far too many possible locations storing our desired value. If you count misaligned locations, this means there is a different location to address every single byte in memory. A program with one megabyte of memory already has a &lt;em&gt;million&lt;&#x2F;em&gt; of addresses. Clearly, we need to do better than performing one million memory reads&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt; +&lt;p&gt;This post will shift focus a bit from using &lt;code&gt;winapi&lt;&#x2F;code&gt; to possible techniques to perform the various scans.&lt;&#x2F;p&gt; +&lt;h2 id=&quot;unknown-initial-value&quot;&gt;Unknown initial value&lt;&#x2F;h2&gt; +&lt;details open&gt;&lt;summary&gt;Cheat Engine Tutorial: Step 3&lt;&#x2F;summary&gt; +&lt;blockquote&gt; +&lt;p&gt;Ok, seeing that you&#x27;ve figured out how to find a value using exact value let&#x27;s move on to the next step.&lt;&#x2F;p&gt; +&lt;p&gt;First things first though. Since you are doing a new scan, you have to click on New Scan first, to start a new scan. (You may think this is straighforward, but you&#x27;d be surprised how many people get stuck on that step) I won&#x27;t be explaining this step again, so keep this in mind +Now that you&#x27;ve started a new scan, let&#x27;s continue&lt;&#x2F;p&gt; +&lt;p&gt;In the previous test we knew the initial value so we could do a exact value, but now we have a status bar where we don&#x27;t know the starting value. +We only know that the value is between 0 and 500. And each time you click &#x27;hit me&#x27; you lose some health. The amount you lose each time is shown above the status bar.&lt;&#x2F;p&gt; +&lt;p&gt;Again there are several different ways to find the value. (like doing a decreased value by... scan), but I&#x27;ll only explain the easiest. &amp;quot;Unknown initial value&amp;quot;, and decreased value. +Because you don&#x27;t know the value it is right now, a exact value wont do any good, so choose as scantype &#x27;Unknown initial value&#x27;, again, the value type is 4-bytes. (most windows apps use 4-bytes)click first scan and wait till it&#x27;s done.&lt;&#x2F;p&gt; +&lt;p&gt;When it is done click &#x27;hit me&#x27;. You&#x27;ll lose some of your health. (the amount you lost shows for a few seconds and then disappears, but you don&#x27;t need that) +Now go to Cheat Engine, and choose &#x27;Decreased Value&#x27; and click &#x27;Next Scan&#x27; +When that scan is done, click hit me again, and repeat the above till you only find a few.&lt;&#x2F;p&gt; +&lt;p&gt;We know the value is between 0 and 500, so pick the one that is most likely the address we need, and add it to the list. +Now change the health to 5000, to proceed to the next step.&lt;&#x2F;p&gt; +&lt;&#x2F;blockquote&gt; +&lt;&#x2F;details&gt; +&lt;h2 id=&quot;dense-memory-locations&quot;&gt;Dense memory locations&lt;&#x2F;h2&gt; +&lt;p&gt;The key thing to notice here is that, when we read memory from another process, we do so over &lt;em&gt;entire regions&lt;&#x2F;em&gt;. A memory region is represented by a starting offset, a size, and a bunch of other things like protection level.&lt;&#x2F;p&gt; +&lt;p&gt;When running the first scan for an unknown value, all we need to remember is the starting offset and size for every single region. All the candidate locations that could point to our value fall within this range, so it is enough for us to store the range definition, and not every location within it.&lt;&#x2F;p&gt; +&lt;p&gt;To gain a better understanding of what this means, let&#x27;s come up with a more specific scenario. With our current approach of doing things, we store an address (&lt;code&gt;usize&lt;&#x2F;code&gt;) for every location pointing to our desired value. In the case of unknown values, all locations are equally valid, since we don&#x27;t know what value they should point to yet, and any value they point to is good. With this representation, we would end up with a very large vector:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let locations = vec![0x2000, 0x2001, ..., 0x20ff, 0x2100]; +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;This representation is dense. Every single number in the range &lt;code&gt;0x2000..=0x2100&lt;&#x2F;code&gt; is present. So why bother storing the values individually when the range is enough?:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let locations = EntireRegion { range: 0x2000..=0x2100 }; +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Much better! With two &lt;code&gt;usize&lt;&#x2F;code&gt;, one for the starting location and another for the end, we can indicate that we care about all the locations falling in that range.&lt;&#x2F;p&gt; +&lt;p&gt;In fact, some accessible memory regions immediately follow eachother, so we could even compact this further and merge regions which are together. But due to their potential differences with regards to protection levels, we will not attempt to merge regions.&lt;&#x2F;p&gt; +&lt;p&gt;We don&#x27;t want to get rid of the old way of storing locations, because once we start narrowing them down, we will want to go back to storing just a few candidates. To keep things tidy, let&#x27;s introduce a new &lt;code&gt;enum&lt;&#x2F;code&gt; representing either possibility:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use std::ops::Range; + +pub enum CandidateLocations { + Discrete { + locations: Vec&amp;lt;usize&amp;gt;, + }, + Dense { + range: Range&amp;lt;usize&amp;gt;, + } +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Let&#x27;s also introduce another &lt;code&gt;enum&lt;&#x2F;code&gt; to perform the different scan types. For the time being, we will only worry about looking for &lt;code&gt;i32&lt;&#x2F;code&gt; in memory:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan { + Exact(i32), + Unknown, +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;h2 id=&quot;storing-scanned-values&quot;&gt;Storing scanned values&lt;&#x2F;h2&gt; +&lt;p&gt;When scanning for exact values, it&#x27;s not necessary to store the value found. We already know they&#x27;re all the same, for example, value &lt;code&gt;42&lt;&#x2F;code&gt;. However, if the value is unknown, we do need to store it so that we can compare it in a subsequent scan to see if the value is the same or it changed. This means the value can be &amp;quot;any within&amp;quot; the read memory chunk:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Value { + Exact(i32), + AnyWithin(Vec&amp;lt;u8&amp;gt;), +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;For every region in memory, there will be some candidate locations and a value (or value range) we need to compare against in subsequent scans:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub struct Region { + pub info: winapi::um::winnt::MEMORY_BASIC_INFORMATION, + pub locations: CandidateLocations, + pub value: Value, +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;With all the data structures needed setup, we can finally refactor our old scanning code into a new method capable of dealing with all these cases. For brevity, I will omit the exact scan, as it remains mostly unchanged:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use winapi::um::winnt::MEMORY_BASIC_INFORMATION; + +... + +&#x2F;&#x2F; inside `impl Process` +pub fn scan_regions(&amp;amp;self, regions: &amp;amp;[MEMORY_BASIC_INFORMATION], scan: Scan) -&amp;gt; Vec&amp;lt;Region&amp;gt; { + regions + .iter() + .flat_map(|region| match scan { + Scan::Exact(n) =&amp;gt; todo!(&amp;quot;old scan implementation&amp;quot;), + Scan::Unknown =&amp;gt; { + let base = region.BaseAddress as usize; + match self.read_memory(region.BaseAddress as _, region.RegionSize) { + Ok(memory) =&amp;gt; Some(Region { + info: region.clone(), + locations: CandidateLocations::Dense { + range: base..base + region.RegionSize, + }, + value: Value::AnyWithin(memory), + }), + Err(_) =&amp;gt; None, + } + } + }) + .collect() +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Time to try it out!&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;impl CandidateLocations { + pub fn len(&amp;amp;self) -&amp;gt; usize { + match self { + CandidateLocations::Discrete { locations } =&amp;gt; locations.len(), + CandidateLocations::Dense { range } =&amp;gt; range.len(), + } + } +} + +... + +fn main() { + &#x2F;&#x2F; -snip- + + println!(&amp;quot;Scanning {} memory regions&amp;quot;, regions.len()); + let last_scan = process.scan_regions(&amp;amp;regions, Scan::Unknown); + println!( + &amp;quot;Found {} locations&amp;quot;, + last_scan.iter().map(|r| r.locations.len()).sum::&amp;lt;usize&amp;gt;() + ); +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;pre&gt;&lt;code&gt;Scanning 88 memory regions +Found 3014656 locations +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;If we consider misaligned locations, there is a lot of potential addresses where we could look for. Running the same scan on Cheat Engine yields &lt;code&gt;2,449,408&lt;&#x2F;code&gt; addresses, which is pretty close. It&#x27;s probably skipping some additional regions that we are considering. Emulating Cheat Engine to perfection is not a concern for us at the moment, so I&#x27;m not going to investigate what regions it actually uses.&lt;&#x2F;p&gt; +&lt;h2 id=&quot;comparing-scanned-values&quot;&gt;Comparing scanned values&lt;&#x2F;h2&gt; +&lt;p&gt;Now that we have performed the initial scan and have stored all the &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt; and &lt;code&gt;Value&lt;&#x2F;code&gt;, we can re-implement the &amp;quot;next scan&amp;quot; step to handle any variant of our &lt;code&gt;Scan&lt;&#x2F;code&gt; enum. This enables us to mix-and-match any &lt;code&gt;Scan&lt;&#x2F;code&gt; mode in any order. For example, one could perform an exact scan, then one for decreased values, or start with unknown scan and scan for unchanged values.&lt;&#x2F;p&gt; +&lt;p&gt;The tutorial suggests using &amp;quot;decreased value&amp;quot; scan, so let&#x27;s start with that:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan { + Exact(i32), + Unknown, + Decreased, &#x2F;&#x2F; new! +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Other scanning modes, such as decreased by a known amount rather than any decrease, increased, unchanged, changed and so on, are not very different from the &amp;quot;decreased&amp;quot; scan, so I won&#x27;t bore you with the details.&lt;&#x2F;p&gt; +&lt;p&gt;I will use a different method to perform a &amp;quot;rescan&amp;quot;, since the first one is a bit more special in that it doesn&#x27;t start with any previous values:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rescan_regions(&amp;amp;self, regions: &amp;amp;[Region], scan: Scan) -&amp;gt; Vec&amp;lt;Region&amp;gt; { + regions + .iter() + .flat_map(|region| match scan { + Scan::Decreased =&amp;gt; { + let mut locations = Vec::new(); + match region.locations { + CandidateLocations::Dense { range } =&amp;gt; { + match self.read_memory(range.start, range.end - range.start) { + Ok(memory) =&amp;gt; match region.value { + Value::AnyWithin(previous) =&amp;gt; { + memory + .windows(4) + .zip(previous.windows(4)) + .enumerate() + .step_by(4) + .for_each(|(offset, (new, old))| { + let new = i32::from_ne_bytes([ + new[0], new[1], new[2], new[3], + ]); + let old = i32::from_ne_bytes([ + old[0], old[1], old[2], old[3], + ]); + if new &amp;lt; old { + locations.push(range.start + offset); + } + }); + + Some(Region { + info: region.info.clone(), + locations: CandidateLocations::Discrete { locations }, + value: Value::AnyWithin(memory), + }) + } + _ =&amp;gt; todo!(), + }, + _ =&amp;gt; todo!(), + } + } + _ =&amp;gt; todo!(), + } + } + _ =&amp;gt; todo!(), + }) + .collect() +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;If you&#x27;ve skimmed over that, I do not blame you. Here&#x27;s the summary: for every existing region, when executing the scan mode &amp;quot;decreased&amp;quot;, if the previous locations were dense, read the entire memory region. On success, if the previous values were a chunk of memory, iterate over the current and old memory at the same time, and for every aligned &lt;code&gt;i32&lt;&#x2F;code&gt;, if the new value is less, store it.&lt;&#x2F;p&gt; +&lt;p&gt;It&#x27;s also making me ill. Before I leave a mess on the floor, does it work?&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;std::thread::sleep(std::time::Duration::from_secs(10)); +let last_scan = process.rescan_regions(&amp;amp;last_scan, Scan::Decreased); +println!( + &amp;quot;Found {} locations&amp;quot;, + last_scan.iter().map(|r| r.locations.len()).sum::&amp;lt;usize&amp;gt;() +); +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;Found 3014656 locations +Found 177 locations +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Okay, great, let&#x27;s clean up this mess…&lt;&#x2F;p&gt; +&lt;h2 id=&quot;refactoring&quot;&gt;Refactoring&lt;&#x2F;h2&gt; +&lt;p&gt;Does it also make you uncomfortable to be writing something that you know will end up &lt;em&gt;huge&lt;&#x2F;em&gt; unless you begin refactoring other parts right now? I definitely feel that way. But I think it&#x27;s good discipline to push through with something that works first, even if it&#x27;s nasty, before going on a tangent. Now that we have the basic implementation working, let&#x27;s take on this monster before it eats us alive.&lt;&#x2F;p&gt; +&lt;p&gt;First things first, that method is inside an &lt;code&gt;impl&lt;&#x2F;code&gt; block. The deepest nesting level is 13. I almost have to turn around my chair to read the entire thing out!&lt;&#x2F;p&gt; +&lt;p&gt;Second, we&#x27;re nesting four matches. Three of them we care about: scan, candidate location, and value. If each of these &lt;code&gt;enum&lt;&#x2F;code&gt; has &lt;code&gt;S&lt;&#x2F;code&gt;, &lt;code&gt;C&lt;&#x2F;code&gt; and &lt;code&gt;V&lt;&#x2F;code&gt; variants respectively, writing each of these by hand will require &lt;code&gt;S * C * V&lt;&#x2F;code&gt; different implementations! Cheat Engine offers 10 different scans, I can think of at least 3 different ways to store candidate locations, and another 3 ways to store the values found. That&#x27;s &lt;code&gt;10 * 3 * 3 = 90&lt;&#x2F;code&gt; different combinations. I am not willing to write out all these&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, so we need to start introducing some abstractions. Just imagine what a monster function you would end with! The horror!&lt;&#x2F;p&gt; +&lt;p&gt;Third, why is the scan being executed in the process? This is something that should be done in the &lt;code&gt;impl Scan&lt;&#x2F;code&gt; instead!&lt;&#x2F;p&gt; +&lt;p&gt;Let&#x27;s begin the cleanup:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rescan_regions(&amp;amp;self, regions: &amp;amp;[Region], scan: Scan) -&amp;gt; Vec&amp;lt;Region&amp;gt; { + todo!() +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;I already feel ten times better.&lt;&#x2F;p&gt; +&lt;p&gt;Now, this method will unconditionally read the entire memory region, even if the scan or the previous candidate locations don&#x27;t need it&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. In the worst case with a single discrete candidate location, we will be reading a very large chunk of memory when we could have read just the 4 bytes needed for the &lt;code&gt;i32&lt;&#x2F;code&gt;. On the bright side, if there &lt;em&gt;are&lt;&#x2F;em&gt; more locations in this memory region, we will get read of them at the same time&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. So even if we&#x27;re moving more memory around all the time, it isn&#x27;t &lt;em&gt;too&lt;&#x2F;em&gt; bad.&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;regions + .iter() + .flat_map( + |region| match self.read_memory(region.info.BaseAddress as _, region.info.RegionSize) { + Ok(memory) =&amp;gt; todo!(), + Err(err) =&amp;gt; { + eprintln!( + &amp;quot;Failed to read {} bytes at {:?}: {}&amp;quot;, + region.info.RegionSize, region.info.BaseAddress, err, + ); + None + } + }, + ) + .collect() +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Great! If reading memory succeeds, we want to rerun the scan:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;Ok(memory) =&amp;gt; Some(scan.rerun(region, memory)), +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;The rerun will live inside &lt;code&gt;impl Scan&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rerun(&amp;amp;self, region: &amp;amp;Region, memory: Vec&amp;lt;u8&amp;gt;) -&amp;gt; Region { + match self { + Scan::Exact(_) =&amp;gt; self.run(region.info.clone(), memory), + Scan::Unknown =&amp;gt; region.clone(), + Scan::Decreased =&amp;gt; todo!(), + } +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;An exact scan doesn&#x27;t care about any previous values, so it behaves like a first scan. The first scan is done by the &lt;code&gt;run&lt;&#x2F;code&gt; function (it contains the implementation factored out of the &lt;code&gt;Process::scan_regions&lt;&#x2F;code&gt; method), which only needs the region information and the current memory chunk we just read.&lt;&#x2F;p&gt; +&lt;p&gt;The unknown scan leaves the region unchanged: any value stored is still valid, because it is unknown what we&#x27;re looking for.&lt;&#x2F;p&gt; +&lt;p&gt;The decreased scan will have to iterate over all the candidate locations, and compare them with the current memory chunk. But this time, we&#x27;ll abstract this iteration too:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;impl Region { + fn iter_locations&amp;lt;&#x27;a&amp;gt;( + &amp;amp;&#x27;a self, + new_memory: &amp;amp;&#x27;a [u8], + ) -&amp;gt; impl Iterator&amp;lt;Item = (usize, i32, i32)&amp;gt; + &#x27;a { + match &amp;amp;self.locations { + CandidateLocations::Dense { range } =&amp;gt; range.clone().step_by(4).map(move |addr| { + let old = self.value_at(addr); + let new = i32::from_ne_bytes([ + new_memory[0], + new_memory[1], + new_memory[2], + new_memory[3], + ]); + (addr, old, new) + }), + _ =&amp;gt; todo!(), + } + } +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;For a dense candidate location, we iterate over all the 4-aligned addresses (fast scan for &lt;code&gt;i32&lt;&#x2F;code&gt; values), and yield &lt;code&gt;(current address, old value, new value)&lt;&#x2F;code&gt;. This way, the &lt;code&gt;Scan&lt;&#x2F;code&gt; can do anything it wants with the old and new values, and if it finds a match, it can use the address.&lt;&#x2F;p&gt; +&lt;p&gt;The &lt;code&gt;value_at&lt;&#x2F;code&gt; method will deal with all the &lt;code&gt;Value&lt;&#x2F;code&gt; variants:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn value_at(&amp;amp;self, addr: usize) -&amp;gt; i32 { + match &amp;amp;self.value { + Value::AnyWithin(chunk) =&amp;gt; { + let base = addr - self.info.BaseAddress as usize; + let bytes = &amp;amp;chunk[base..base + 4]; + i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) + } + _ =&amp;gt; todo!(), + } +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;This way, &lt;code&gt;iter_locations&lt;&#x2F;code&gt; can easily use any value type. With this, we have all &lt;code&gt;enum&lt;&#x2F;code&gt; covered: &lt;code&gt;Scan&lt;&#x2F;code&gt; in &lt;code&gt;rerun&lt;&#x2F;code&gt;, &lt;code&gt;CandidateLocation&lt;&#x2F;code&gt; in &lt;code&gt;iter_locations&lt;&#x2F;code&gt;, and &lt;code&gt;Value&lt;&#x2F;code&gt; in &lt;code&gt;value_at&lt;&#x2F;code&gt;. Now we can add as many variants as we want, and we will only need to update a single &lt;code&gt;match&lt;&#x2F;code&gt; arm for each of them. Let&#x27;s implement &lt;code&gt;Scan::Decreased&lt;&#x2F;code&gt; and try it out:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rerun(&amp;amp;self, region: &amp;amp;Region, memory: Vec&amp;lt;u8&amp;gt;) -&amp;gt; Region { + match self { + Scan::Decreased =&amp;gt; Region { + info: region.info.clone(), + locations: CandidateLocations::Discrete { + locations: region + .iter_locations(&amp;amp;memory) + .flat_map(|(addr, old, new)| if new &amp;lt; old { Some(addr) } else { None }) + .collect(), + }, + value: Value::AnyWithin(memory), + },, + } +} +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;pre&gt;&lt;code&gt;Found 3014656 locations +Found 223791 locations +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;p&gt;Hmm… before we went down from &lt;code&gt;3014656&lt;&#x2F;code&gt; to &lt;code&gt;177&lt;&#x2F;code&gt; locations, and now we went down to &lt;code&gt;223791&lt;&#x2F;code&gt;. Where did we go wrong?&lt;&#x2F;p&gt; +&lt;p&gt;After spending several hours on this, I can tell you where we went wrong. &lt;code&gt;iter_locations&lt;&#x2F;code&gt; is always accessing the memory range &lt;code&gt;0..4&lt;&#x2F;code&gt;, and not the right address. Here&#x27;s the fix:&lt;&#x2F;p&gt; +&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;CandidateLocations::Dense { range } =&amp;gt; range.clone().step_by(4).map(move |addr| { + let old = self.value_at(addr); + let base = addr - self.info.BaseAddress as usize; + let bytes = &amp;amp;new_memory[base..base + 4]; + let new = i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); + (addr, old, new) +}), +&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; +&lt;h2 id=&quot;going-beyond&quot;&gt;Going beyond&lt;&#x2F;h2&gt; +&lt;p&gt;Let&#x27;s take a look at other possible &lt;code&gt;Scan&lt;&#x2F;code&gt; types. Cheat Engine supports the following initial scan types:&lt;&#x2F;p&gt; +&lt;ul&gt; +&lt;li&gt;Exact Value&lt;&#x2F;li&gt; +&lt;li&gt;Bigger than…&lt;&#x2F;li&gt; +&lt;li&gt;Smaller than…&lt;&#x2F;li&gt; +&lt;li&gt;Value between…&lt;&#x2F;li&gt; +&lt;li&gt;Unknown initial value&lt;&#x2F;li&gt; +&lt;&#x2F;ul&gt; +&lt;p&gt;&amp;quot;Bigger than&amp;quot; and &amp;quot;Smaller than&amp;quot; can both be represented by &amp;quot;Value between&amp;quot;, so it&#x27;s pretty much just three.&lt;&#x2F;p&gt; +&lt;p&gt;For subsequent scans, in addition to the scan types described above, we find:&lt;&#x2F;p&gt; +&lt;ul&gt; +&lt;li&gt;Increased value&lt;&#x2F;li&gt; +&lt;li&gt;Increased value by…&lt;&#x2F;li&gt; +&lt;li&gt;Decreased value&lt;&#x2F;li&gt; +&lt;li&gt;Decreased value by…&lt;&#x2F;li&gt; +&lt;li&gt;Changed value&lt;&#x2F;li&gt; +&lt;li&gt;Unchanged value&lt;&#x2F;li&gt; +&lt;&#x2F;ul&gt; +&lt;p&gt;Not only does Cheat Engine provide all of these scans, but all of them can also be negated. For example, &amp;quot;find values that were not increased by 7&amp;quot;. One could imagine to also support things like &amp;quot;increased value by range&amp;quot;. For the increased and decreased scans, Cheat Engine also supports &amp;quot;at least xx%&amp;quot;, so that if the value changed within the specified percentage interval, it will be considered.&lt;&#x2F;p&gt; +&lt;p&gt;What about &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt;? I can&#x27;t tell you how Cheat Engine stores these, but I can tell you that &lt;code&gt;CandidateLocations::Discrete&lt;&#x2F;code&gt; can still be quite inefficient. Imagine you&#x27;ve started with a scan for unknown values and then ran a scan for unchanged valueus. Most values in memory will have been unchanged, but with our current implementation, we are now storing an entire &lt;code&gt;usize&lt;&#x2F;code&gt; address for each of these. One option would be to introduce &lt;code&gt;CandidateLocations::Sparse&lt;&#x2F;code&gt;, which would be a middle ground. You could implement it like &lt;code&gt;Dense&lt;&#x2F;code&gt; and include a vector of booleans telling you which values to consider, or go smaller and use a bitstring or bit vector. You could use a sparse vector data structure.&lt;&#x2F;p&gt; +&lt;p&gt;&lt;code&gt;Value&lt;&#x2F;code&gt; is very much like &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt;, except that it stores a value to compare against and not an address. Here we can either have an exact value, or an older copy of the memory. Again, keeping a copy of the entire memory chunk when all we need is a handful of values is inefficient. You could keep a mapping from addresses to values if you don&#x27;t have too many. Or you could shrink and fragment the copied memory in a more optimal way. There&#x27;s a lot of room for improvement!&lt;&#x2F;p&gt; +&lt;p&gt;What if, despite all of the efforts above, we still don&#x27;t have enough RAM to store all this information? The Cheat Engine Tutorial doesn&#x27;t use a lot of memory, but as soon as you try scanning bigger programs, like games, you may find yourself needing several gigabytes worth of memory to remember all the found values in order to compare them in subsequent scans. You may even need to consider dumping all the regions to a file and read from it to run the comparisons. For example, running a scan for &amp;quot;unknown value&amp;quot; in Cheat Engine brings its memory up by the same amount of memory used by the process scanned (which makes sense), but as soon as I ran a scan for &amp;quot;unchanged value&amp;quot; over the misaligned values, Cheat Engine&#x27;s disk usage skyrocketed to 1GB&#x2F;s (!) for several seconds on my SSD. After it finished, memory usage went down to normal. It was very likely writing out all candidate locations to disk.&lt;&#x2F;p&gt; +&lt;h2 id=&quot;finale&quot;&gt;Finale&lt;&#x2F;h2&gt; +&lt;p&gt;There is a lot of things to learn from Cheat Engine just by observing its behaviour, and we&#x27;re only scratching its surface.&lt;&#x2F;p&gt; +&lt;p&gt;In the next post, we&#x27;ll tackle the fourth step of the tutorial: Floating points. So far, we have only been working with &lt;code&gt;i32&lt;&#x2F;code&gt; for simplicity. We will need to update our code to be able to account for different data types, which will make it easy to support other types like &lt;code&gt;i16&lt;&#x2F;code&gt;, &lt;code&gt;i64&lt;&#x2F;code&gt;, or even strings, represented as an arbitrary sequence of bytes.&lt;&#x2F;p&gt; +&lt;p&gt;As usual, you can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lonami&#x2F;memo&quot;&gt;obtain the code for this post&lt;&#x2F;a&gt; over at my GitHub. You can run &lt;code&gt;git checkout step3&lt;&#x2F;code&gt; after cloning the repository to get the right version of the code. This version is a bit cleaner than the one presented in the blog, and contains some of the things described in the &lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;woce-3&#x2F;#going-beyond&quot;&gt;Going beyond&lt;&#x2F;a&gt; section. Until next time!&lt;&#x2F;p&gt; +&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h3&gt; +&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt; +&lt;p&gt;Well, technically, we will perform a million memory reads&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The issue here is the million calls to &lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt;, not reading memory per se.&lt;&#x2F;p&gt; +&lt;&#x2F;div&gt; +&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt; +&lt;p&gt;Not currently. After a basic implementation works, writing each implementation by hand and fine-tuning them by treating each of them as a special case could yield significant speed improvements. So although it would be a lot of work, this option shouldn&#x27;t be ruled out completely.&lt;&#x2F;p&gt; +&lt;&#x2F;div&gt; +&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt; +&lt;p&gt;You could ask the candidate locations where one should read, which would still keep the code reasonably simple.&lt;&#x2F;p&gt; +&lt;&#x2F;div&gt; +&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt; +&lt;p&gt;You could also optimize for this case by determining both the smallest and largest address, and reading enough to cover them both. Or apply additional heuristics to only do so if the ratio of the size you&#x27;re reading compared to the size you need isn&#x27;t too large and abort the joint read otherwise. There is a lot of room for optimization here.&lt;&#x2F;p&gt; +&lt;&#x2F;div&gt; +&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt; +&lt;p&gt;(A footnote in a footnote?) The machine registers, memory cache and compiler will all help lower this cost, so the generated executable might not actually need that many reads from RAM. But that&#x27;s getting way too deep into the details now.&lt;&#x2F;p&gt; +&lt;&#x2F;div&gt; +</content> + </entry> + <entry xml:lang="en"> <title>Writing our own Cheat Engine: Exact Value scanning</title> <published>2021-02-12T00:00:00+00:00</published> - <updated>2021-02-16T00:00:00+00:00</updated> + <updated>2021-02-19T00:00:00+00:00</updated> <link href="https://lonami.dev/blog/woce-2/" type="text/html"/> <id>https://lonami.dev/blog/woce-2/</id> <content type="html">&lt;p&gt;This is part 2 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-1&quot;&gt;Part 1: Introduction&lt;&#x2F;a&gt; (start here if you&#x27;re new to the series!)&lt;&#x2F;li&gt; &lt;li&gt;Part 2: Exact Value scanning&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;Part 3: Unknown initial value&lt;&#x2F;a&gt;&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;p&gt;In the introduction, we spent a good deal of time enumerating all running processes just so we could find out the pid we cared about. With the pid now in our hands, we can do pretty much anything to its corresponding process.&lt;&#x2F;p&gt; &lt;p&gt;It&#x27;s now time to read the process&#x27; memory and write to it. If our process was a single-player game, this would enable us to do things like setting a very high value on the player&#x27;s current health pool, making us invincible. This technique will often not work for multi-player games, because the server likely knows your true current health (the most you could probably do is make the client render an incorrect value). However, if the server is crappy and it trusts the client, then you&#x27;re still free to mess around with your current health.&lt;&#x2F;p&gt;

@@ -334,7 +688,7 @@ locations.retain(...);

} &lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; &lt;h2 id=&quot;modifying-memory&quot;&gt;Modifying memory&lt;&#x2F;h2&gt; -&lt;p&gt;Now that we have very likely locations pointing to our current health in memory, all that&#x27;s left is writing our new desired value to gain infinite health&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Much like there&#x27;s a call to &lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt;, there&#x27;s a different one to &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;memoryapi&#x2F;nf-memoryapi-writeprocessmemory&quot;&gt;&lt;code&gt;WriteProcessMemory&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Its usage is straightforward:&lt;&#x2F;p&gt; +&lt;p&gt;Now that we have very likely locations pointing to our current health in memory, all that&#x27;s left is writing our new desired value to gain infinite health&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Much like how we&#x27;re able to read memory with &lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt;, we can write to it with &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;memoryapi&#x2F;nf-memoryapi-writeprocessmemory&quot;&gt;&lt;code&gt;WriteProcessMemory&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Its usage is straightforward:&lt;&#x2F;p&gt; &lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn write_memory(&amp;amp;self, addr: usize, value: &amp;amp;[u8]) -&amp;gt; io::Result&amp;lt;usize&amp;gt; { let mut written = 0;

@@ -428,13 +782,14 @@ </entry>

<entry xml:lang="en"> <title>Writing our own Cheat Engine: Introduction</title> <published>2021-02-07T00:00:00+00:00</published> - <updated>2021-02-16T00:00:00+00:00</updated> + <updated>2021-02-19T00:00:00+00:00</updated> <link href="https://lonami.dev/blog/woce-1/" type="text/html"/> <id>https://lonami.dev/blog/woce-1/</id> <content type="html">&lt;p&gt;This is part 1 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt; &lt;ul&gt; &lt;li&gt;Part 1: Introduction&lt;&#x2F;li&gt; &lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;Part 2: Exact Value scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;Part 3: Unknown initial value&lt;&#x2F;a&gt;&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cheatengine.org&#x2F;&quot;&gt;Cheat Engine&lt;&#x2F;a&gt; is a tool designed to modify single player games and contains other useful tools within itself that enable its users to debug games or other applications. It comes with a memory scanner, (dis)assembler, inspection tools and a handful other things. In this series, we will be writing our own tiny Cheat Engine capable of solving all steps of the tutorial, and diving into how it all works underneath.&lt;&#x2F;p&gt; &lt;p&gt;Needless to say, we&#x27;re doing this for private and educational purposes only. One has to make sure to not violate the EULA or ToS of the specific application we&#x27;re attaching to. This series, much like cheatengine.org, does not condone the illegal use of the code shared.&lt;&#x2F;p&gt;

@@ -1984,94 +2339,95 @@ </entry>

<entry xml:lang="en"> <title>Atemporal Blog Posts</title> <published>2018-02-03T00:00:00+00:00</published> - <updated>2018-02-03T00:00:00+00:00</updated> + <updated>2021-02-19T00:00:00+00:00</updated> <link href="https://lonami.dev/blog/posts/" type="text/html"/> <id>https://lonami.dev/blog/posts/</id> <content type="html">&lt;p&gt;These are some interesting posts and links I&#x27;ve found around the web. I believe they are quite interesting and nice reads, so if you have the time, I encourage you to check some out.&lt;&#x2F;p&gt; &lt;h2 id=&quot;algorithms&quot;&gt;Algorithms&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;http:&#x2F;&#x2F;www.tannerhelland.com&#x2F;4660&#x2F;dithering-eleven-algorithms-source-code&#x2F;. Image Dithering: Eleven Algorithms and Source Code. What does it mean and how to achieve it?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;cristian.io&#x2F;post&#x2F;bloom-filters&#x2F;. Idempotence layer on bloom filters. What are they and how can they help?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Huffman_coding. Huffman coding. This encoding is a simple yet interesting way of compressing information.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;github.com&#x2F;mxgmn&#x2F;WaveFunctionCollapse. Wave Function Collapse. Bitmap &amp;amp; tilemap generation from a single example with the help of ideas from quantum mechanics.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;blog.nelhage.com&#x2F;2015&#x2F;02&#x2F;regular-expression-search-with-suffix-arrays&#x2F;. Regular Expression Search with Suffix Arrays. A way to efficiently search large amounts of text.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.tannerhelland.com&#x2F;4660&#x2F;dithering-eleven-algorithms-source-code&#x2F;&quot;&gt;Image Dithering: Eleven Algorithms and Source Code&lt;&#x2F;a&gt;. What does it mean and how to achieve it?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cristian.io&#x2F;post&#x2F;bloom-filters&#x2F;&quot;&gt;Idempotence layer on bloom filters&lt;&#x2F;a&gt;. What are they and how can they help?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Huffman_coding&quot;&gt;Huffman coding&lt;&#x2F;a&gt;. This encoding is a simple yet interesting way of compressing information.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mxgmn&#x2F;WaveFunctionCollapse&quot;&gt;Wave Function Collapse&lt;&#x2F;a&gt;. Bitmap &amp;amp; tilemap generation from a single example with the help of ideas from quantum mechanics.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.nelhage.com&#x2F;2015&#x2F;02&#x2F;regular-expression-search-with-suffix-arrays&#x2F;&quot;&gt;Regular Expression Search with Suffix Arrays&lt;&#x2F;a&gt;. A way to efficiently search large amounts of text.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;culture&quot;&gt;Culture&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.wired.com&#x2F;story&#x2F;ideas-joi-ito-robot-overlords&#x2F;. Why Westerners Fear Robots and the Japanese Do Not. Explains some possible reasons for this case.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;catb.org&#x2F;~esr&#x2F;faqs&#x2F;smart-questions.html. How To Ask Questions The Smart Way. Some bits of hacker culture and amazing tips on how to ask a question.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;apenwarr.ca&#x2F;log&#x2F;?m=201809#14. XML, blockchains, and the strange shapes of progress. Some of history about XML and blockchain.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;czep.net&#x2F;17&#x2F;legion-of-lobotomized-unices.html. Legion of lobotomized unices. A time where computers are treated a lot more nicely.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2016&#x2F;the-expression-problem-and-its-solutions&#x2F;. The Expression Problem and its solutions. What is it and what can we do to solve it?&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;allendowney.blogspot.com&#x2F;2015&#x2F;08&#x2F;the-inspection-paradox-is-everywhere.html. The Inspection Paradox is Everywhere. Interesting and very common phenomena.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;github.com&#x2F;ChrisKnott&#x2F;Algojammer. An experimental code editor for writing algorithms. Contains several links to different tools for reverse debugging.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;habitatchronicles.com&#x2F;2017&#x2F;05&#x2F;what-are-capabilities&#x2F;. What Are Capabilities? Good ideas with great security implications.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;blog.aurynn.com&#x2F;2015&#x2F;12&#x2F;16-contempt-culture. Contempt Culture. Or why you should not speak crap about your non-favourite programming languages.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;tscc3e5eujrsEeFN4&#x2F;well-kept-gardens-die-by-pacifism. Well-Kept Gardens Die By Pacifism. Risks any online community can run into.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;ncase.me&#x2F;. It&#x27;s Nicky Case! They make some cool things worth checking out, I really like &amp;quot;we become what we behold&amp;quot;.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.wired.com&#x2F;story&#x2F;ideas-joi-ito-robot-overlords&#x2F;&quot;&gt;Why Westerners Fear Robots and the Japanese Do Not&lt;&#x2F;a&gt;. Explains some possible reasons for this case.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;catb.org&#x2F;%7Eesr&#x2F;faqs&#x2F;smart-questions.html&quot;&gt;How To Ask Questions The Smart Way&lt;&#x2F;a&gt;. Some bits of hacker culture and amazing tips on how to ask a question.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;apenwarr.ca&#x2F;log&#x2F;?m=201809#14&quot;&gt;XML, blockchains, and the strange shapes of progress&lt;&#x2F;a&gt;. Some of history about XML and blockchain.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;czep.net&#x2F;17&#x2F;legion-of-lobotomized-unices.html&quot;&gt;Legion of lobotomized unices&lt;&#x2F;a&gt;. A time where computers are treated a lot more nicely.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2016&#x2F;the-expression-problem-and-its-solutions&#x2F;&quot;&gt;The Expression Problem and its solutions&lt;&#x2F;a&gt;. What is it and what can we do to solve it?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;allendowney.blogspot.com&#x2F;2015&#x2F;08&#x2F;the-inspection-paradox-is-everywhere.html&quot;&gt;The Inspection Paradox is Everywhere&lt;&#x2F;a&gt;. Interesting and very common phenomena.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ChrisKnott&#x2F;Algojammer&quot;&gt;An experimental code editor for writing algorithms&lt;&#x2F;a&gt;. Contains several links to different tools for reverse debugging.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;habitatchronicles.com&#x2F;2017&#x2F;05&#x2F;what-are-capabilities&#x2F;&quot;&gt;What Are Capabilities?&lt;&#x2F;a&gt; Good ideas with great security implications.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.aurynn.com&#x2F;2015&#x2F;12&#x2F;16-contempt-culture&quot;&gt;Contempt Culture&lt;&#x2F;a&gt;. Or why you should not speak crap about your non-favourite programming languages.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;tscc3e5eujrsEeFN4&#x2F;well-kept-gardens-die-by-pacifism&quot;&gt;Well-Kept Gardens Die By Pacifism&lt;&#x2F;a&gt;. Risks any online community can run into.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;ncase.me&#x2F;&quot;&gt;It&#x27;s Nicky Case!&lt;&#x2F;a&gt; They make some cool things worth checking out, I really like &amp;quot;we become what we behold&amp;quot;.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;debate&quot;&gt;Debate&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;https:&#x2F;&#x2F;steemit.com&#x2F;opensource&#x2F;@crell&#x2F;open-source-is-awful. Open Source is awful. Has some points about why is it bad and how it could improve.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;www.mondo2000.com&#x2F;2018&#x2F;01&#x2F;17&#x2F;pink-lexical-goop-dark-side-autocorrect&#x2F;. Pink Lexical Goop: The Dark Side of Autocorrect. It can shape how you think.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;blog.ploeh.dk&#x2F;2015&#x2F;08&#x2F;03&#x2F;idiomatic-or-idiosyncratic&#x2F;. Idiomatic or idiosyncratic? Can porting code constructs from other languages have a positive effect?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;gamasutra.com&#x2F;view&#x2F;news&#x2F;169296&#x2F;Indepth_Functional_programming_in_C.php. In-depth: Functional programming in C++. Is it useful to bother with functional concepts in a language like C++?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;vorpus.org&#x2F;blog&#x2F;notes-on-structured-concurrency-or-go-statement-considered-harmful&#x2F;. Notes on structured concurrency, or: Go statement considered harmful.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;queue.acm.org&#x2F;detail.cfm?id=3212479. C Is Not a Low-level Language. Could there be alternative programming models designed for more specialized CPUs?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;steemit.com&#x2F;opensource&#x2F;@crell&#x2F;open-source-is-awful&quot;&gt;Open Source is awful&lt;&#x2F;a&gt;. Has some points about why is it bad and how it could improve.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.mondo2000.com&#x2F;2018&#x2F;01&#x2F;17&#x2F;pink-lexical-goop-dark-side-autocorrect&#x2F;&quot;&gt;Pink Lexical Goop: The Dark Side of Autocorrect&lt;&#x2F;a&gt;. It can shape how you think.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.ploeh.dk&#x2F;2015&#x2F;08&#x2F;03&#x2F;idiomatic-or-idiosyncratic&#x2F;&quot;&gt;Idiomatic or idiosyncratic?&lt;&#x2F;a&gt; Can porting code constructs from other languages have a positive effect?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gamasutra.com&#x2F;view&#x2F;news&#x2F;169296&#x2F;Indepth_Functional_programming_in_C.php&quot;&gt;In-depth: Functional programming in C++&lt;&#x2F;a&gt;. Is it useful to bother with functional concepts in a language like C++?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;vorpus.org&#x2F;blog&#x2F;notes-on-structured-concurrency-or-go-statement-considered-harmful&#x2F;&quot;&gt;Notes on structured concurrency, or: Go statement considered harmful&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;queue.acm.org&#x2F;detail.cfm?id=3212479&quot;&gt;C Is Not a Low-level Language&lt;&#x2F;a&gt;. Could there be alternative programming models designed for more specialized CPUs?&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;food-for-thought&quot;&gt;Food for Thought&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.hillelwayne.com&#x2F;post&#x2F;divide-by-zero&#x2F;. 1&#x2F;0 = 0. Explores why it makes sense to redefine mathemathics under some circumstances, and why it is possible to do so.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;jeremykun.com&#x2F;2018&#x2F;04&#x2F;13&#x2F;for-mathematicians-does-not-mean-equality&#x2F;. For mathematicians, = does not mean equality. What other definitions does the equal sign have?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;2MD3NMLBPCqPfnfre&#x2F;cached-thoughts. Cached Thoughts. How is it possible that our brains work at all?&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;tonsky.me&#x2F;blog&#x2F;disenchantment&#x2F;. Software disenchantment. Faster hardware and slower software is a trend. +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.hillelwayne.com&#x2F;post&#x2F;divide-by-zero&#x2F;&quot;&gt;1&#x2F;0 = 0&lt;&#x2F;a&gt;. Explores why it makes sense to redefine mathemathics under some circumstances, and why it is possible to do so.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;jeremykun.com&#x2F;2018&#x2F;04&#x2F;13&#x2F;for-mathematicians-does-not-mean-equality&#x2F;&quot;&gt;For mathematicians, = does not mean equality&lt;&#x2F;a&gt;. What other definitions does the equal sign have?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;2MD3NMLBPCqPfnfre&#x2F;cached-thoughts&quot;&gt;Cached Thoughts&lt;&#x2F;a&gt;. How is it possible that our brains work at all?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;tonsky.me&#x2F;blog&#x2F;disenchantment&#x2F;&quot;&gt;Software disenchantment&lt;&#x2F;a&gt;. Faster hardware and slower software is a trend. &lt;ul&gt; -&lt;li&gt;https:&#x2F;&#x2F;blackhole12.com&#x2F;blog&#x2F;software-engineering-is-bad-but-it-s-not-that-bad&#x2F;. Software Engineering Is Bad, But That&#x27;s Not Why. This post has some good counterpoints to Software disenchantment.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blackhole12.com&#x2F;blog&#x2F;software-engineering-is-bad-but-it-s-not-that-bad&#x2F;&quot;&gt;Software Engineering Is Bad, But That&#x27;s Not Why&lt;&#x2F;a&gt;. This post has some good counterpoints to Software disenchantment.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;. What Color is Your Function? Spoiler: can we approach asynchronous IO better?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;hackernoon.com&#x2F;im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5. I&#x27;m harvesting credit card numbers and passwords from your site. A word of warning when mindlessly adding dependencies.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;medium.com&#x2F;message&#x2F;everything-is-broken-81e5f33a24e1. Everything Is Broken. Some of the (probable) truths about our world.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;&quot;&gt;What Color is Your Function?&lt;&#x2F;a&gt;. Spoiler: can we approach asynchronous IO better?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hackernoon.com&#x2F;im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5&quot;&gt;I&#x27;m harvesting credit card numbers and passwords from your site&lt;&#x2F;a&gt;. A word of warning when mindlessly adding dependencies.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;message&#x2F;everything-is-broken-81e5f33a24e1&quot;&gt;Everything Is Broken&lt;&#x2F;a&gt;. Some of the (probable) truths about our world.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;johnsalvatier.org&#x2F;blog&#x2F;2017&#x2F;reality-has-a-surprising-amount-of-detail&quot;&gt;Reality has a surprising amount of detail&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;funny&quot;&gt;Funny&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;http:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;We-Use-BobX. We Use BobX. BobX.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;the-inner-json-effect. The Inner JSON Effect. For some reason, custom languages are in.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;exponential-backup. Exponential Backup. Far better than git.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;ITAPPMONROBOT. ITAPPMONROBOT. Solving software problems with hardware.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;a-tapestry-of-threads. A Tapestry of Threads.More threads must mean faster code, right?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;medium.com&#x2F;commitlog&#x2F;a-brief-totally-accurate-history-of-programming-languages-cd93ec806124. A Brief Totally Accurate History Of Programming Languages. Don&#x27;t take offense for it!&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;We-Use-BobX&quot;&gt;We Use BobX&lt;&#x2F;a&gt;. BobX.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;the-inner-json-effect&quot;&gt;The Inner JSON Effect&lt;&#x2F;a&gt;. For some reason, custom languages are in.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;exponential-backup&quot;&gt;Exponential Backup&lt;&#x2F;a&gt;. Far better than git.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;ITAPPMONROBOT&quot;&gt;ITAPPMONROBOT&lt;&#x2F;a&gt;. Solving software problems with hardware.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;a-tapestry-of-threads&quot;&gt;A Tapestry of Threads&lt;&#x2F;a&gt;. More threads must mean faster code, right?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;commitlog&#x2F;a-brief-totally-accurate-history-of-programming-languages-cd93ec806124&quot;&gt;A Brief Totally Accurate History Of Programming Languages&lt;&#x2F;a&gt;. Don&#x27;t take offense for it!&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;graphics&quot;&gt;Graphics&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;http:&#x2F;&#x2F;shaunlebron.github.io&#x2F;visualizing-projections&#x2F;. Visualizing Projections. Small post about different projection methods.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;www.iquilezles.org&#x2F;www&#x2F;index.htm. A &lt;em&gt;lot&lt;&#x2F;em&gt; of useful and quality articles regarding computer graphics.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;shaunlebron.github.io&#x2F;visualizing-projections&#x2F;&quot;&gt;Visualizing Projections&lt;&#x2F;a&gt;. Small post about different projection methods.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.iquilezles.org&#x2F;www&#x2F;index.htm&quot;&gt;Inigo Quilez :: fractals, computer graphics, mathematics, shaders, demoscene and more&lt;&#x2F;a&gt; A &lt;em&gt;lot&lt;&#x2F;em&gt; of useful and quality articles regarding computer graphics.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;history&quot;&gt;History&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;https:&#x2F;&#x2F;twobithistory.org&#x2F;2018&#x2F;08&#x2F;18&#x2F;ada-lovelace-note-g.html. What Did Ada Lovelace&#x27;s Program Actually Do?. And other characters that took part in the beginning&#x27;s of programming.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;chrisdown.name&#x2F;2018&#x2F;01&#x2F;02&#x2F;in-defence-of-swap.html. In defence of swap: common misconceptions. Swap is still an useful concept.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.pacifict.com&#x2F;Story&#x2F;. The Graphing Calculator Story. A great classic Apple tale.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;twobithistory.org&#x2F;2018&#x2F;10&#x2F;14&#x2F;lisp.html. How Lisp Became God&#x27;s Own Programming Language. Lisp as a foundational programming language.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twobithistory.org&#x2F;2018&#x2F;08&#x2F;18&#x2F;ada-lovelace-note-g.html&quot;&gt;What Did Ada Lovelace&#x27;s Program Actually Do?&lt;&#x2F;a&gt;. And other characters that took part in the beginning&#x27;s of programming.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chrisdown.name&#x2F;2018&#x2F;01&#x2F;02&#x2F;in-defence-of-swap.html&quot;&gt;In defence of swap: common misconceptions&lt;&#x2F;a&gt;. Swap is still an useful concept.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.pacifict.com&#x2F;Story&#x2F;&quot;&gt;The Graphing Calculator Story&lt;&#x2F;a&gt;. A great classic Apple tale.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twobithistory.org&#x2F;2018&#x2F;10&#x2F;14&#x2F;lisp.html&quot;&gt;How Lisp Became God&#x27;s Own Programming Language&lt;&#x2F;a&gt;. Lisp as a foundational programming language.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;motivational&quot;&gt;Motivational&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2002&#x2F;01&#x2F;06&#x2F;fire-and-motion&#x2F;. Fire And Motion. What does actually take to get things done?&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;realmensch.org&#x2F;2017&#x2F;08&#x2F;25&#x2F;the-parable-of-the-two-programmers&#x2F;. The Parable of the Two Programmers. This tale is about two different types of programmer and their respective endings in a company, illustrating how the one you wouldn&#x27;t expect to actually ends in a better situation.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;byorgey.wordpress.com&#x2F;2018&#x2F;05&#x2F;06&#x2F;conversations-with-a-six-year-old-on-functional-programming&#x2F;. Conversations with a six-year-old on functional programming. Little kids today can be really interested in technological topics.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;bulletproofmusician.com&#x2F;how-many-hours-a-day-should-you-practice&#x2F;. How Many Hours a Day Should You Practice?. While the article is about music, it applies to any other areas.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;nathanmarz.com&#x2F;blog&#x2F;suffering-oriented-programming.html. Suffering-oriented programming. A possibly new approach on how you could tackle your new projects.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;04&#x2F;06&#x2F;things-you-should-never-do-part-i&#x2F;. Things You Should Never Do, Part I. There is no need to rewrite your code.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2002&#x2F;01&#x2F;06&#x2F;fire-and-motion&#x2F;&quot;&gt;Fire And Motion&lt;&#x2F;a&gt;. What does actually take to get things done?&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;realmensch.org&#x2F;2017&#x2F;08&#x2F;25&#x2F;the-parable-of-the-two-programmers&#x2F;&quot;&gt;The Parable of the Two Programmers&lt;&#x2F;a&gt;. This tale is about two different types of programmer and their respective endings in a company, illustrating how the one you wouldn&#x27;t expect to actually ends in a better situation.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;byorgey.wordpress.com&#x2F;2018&#x2F;05&#x2F;06&#x2F;conversations-with-a-six-year-old-on-functional-programming&#x2F;&quot;&gt;Conversations with a six-year-old on functional programming&lt;&#x2F;a&gt;. Little kids today can be really interested in technological topics.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bulletproofmusician.com&#x2F;how-many-hours-a-day-should-you-practice&#x2F;&quot;&gt;How Many Hours a Day Should You Practice?&lt;&#x2F;a&gt;. While the article is about music, it applies to any other areas.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;nathanmarz.com&#x2F;blog&#x2F;suffering-oriented-programming.html&quot;&gt;Suffering-oriented programming&lt;&#x2F;a&gt;. A possibly new approach on how you could tackle your new projects.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;04&#x2F;06&#x2F;things-you-should-never-do-part-i&#x2F;&quot;&gt;Things You Should Never Do, Part I&lt;&#x2F;a&gt;. There is no need to rewrite your code.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; &lt;h2 id=&quot;optimization&quot;&gt;Optimization&lt;&#x2F;h2&gt; &lt;ul&gt; -&lt;li&gt;http:&#x2F;&#x2F;blog.llvm.org&#x2F;2011&#x2F;05&#x2F;what-every-c-programmer-should-know.html. What Every C Programmer Should Know About Undefined Behavior #1&#x2F;3. Explains what undefined behaviour is and why it makes sense.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;ridiculousfish.com&#x2F;blog&#x2F;posts&#x2F;labor-of-division-episode-i.html. Labor of Division (Episode I). Some tricks to divide without division.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;blog.moertel.com&#x2F;posts&#x2F;2013-12-14-great-old-timey-game-programming-hack.html. A Great Old-Timey Game-Programming Hack. Abusing instructions to make games playable even on the slowest hardware.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20191213224640&#x2F;https:&#x2F;&#x2F;people.eecs.berkeley.edu&#x2F;~sangjin&#x2F;2012&#x2F;12&#x2F;21&#x2F;epoll-vs-kqueue.html. Scalable Event Multiplexing: epoll vs kqueue. How good OS primitives can really help performance and scability.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;adamdrake.com&#x2F;command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html. Command-line Tools can be 235x Faster than your Hadoop Cluster. Or how to use the right tool for the right job.&lt;&#x2F;li&gt; -&lt;li&gt;https:&#x2F;&#x2F;nullprogram.com&#x2F;blog&#x2F;2018&#x2F;05&#x2F;27&#x2F;. When FFI Function Calls Beat Native C. How lua beat C at it and the explanation behind it.&lt;&#x2F;li&gt; -&lt;li&gt;http:&#x2F;&#x2F;igoro.com&#x2F;archive&#x2F;gallery-of-processor-cache-effects&#x2F;. Gallery of Processor Cache Effects. Knowing a few things about the cache can make a big difference.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.llvm.org&#x2F;2011&#x2F;05&#x2F;what-every-c-programmer-should-know.html&quot;&gt;What Every C Programmer Should Know About Undefined Behavior #1&#x2F;3&lt;&#x2F;a&gt;. Explains what undefined behaviour is and why it makes sense.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;ridiculousfish.com&#x2F;blog&#x2F;posts&#x2F;labor-of-division-episode-i.html&quot;&gt;Labor of Division (Episode I)&lt;&#x2F;a&gt;. Some tricks to divide without division.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.moertel.com&#x2F;posts&#x2F;2013-12-14-great-old-timey-game-programming-hack.html&quot;&gt;A Great Old-Timey Game-Programming Hack&lt;&#x2F;a&gt;. Abusing instructions to make games playable even on the slowest hardware.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20191213224640&#x2F;https:&#x2F;&#x2F;people.eecs.berkeley.edu&#x2F;%7Esangjin&#x2F;2012&#x2F;12&#x2F;21&#x2F;epoll-vs-kqueue.html&quot;&gt;Scalable Event Multiplexing: epoll vs kqueue&lt;&#x2F;a&gt;. How good OS primitives can really help performance and scability.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;adamdrake.com&#x2F;command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html&quot;&gt;Command-line Tools can be 235x Faster than your Hadoop Cluster&lt;&#x2F;a&gt;. Or how to use the right tool for the right job.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nullprogram.com&#x2F;blog&#x2F;2018&#x2F;05&#x2F;27&#x2F;&quot;&gt;When FFI Function Calls Beat Native C&lt;&#x2F;a&gt;. How lua beat C at it and the explanation behind it.&lt;&#x2F;li&gt; +&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;igoro.com&#x2F;archive&#x2F;gallery-of-processor-cache-effects&#x2F;&quot;&gt;Gallery of Processor Cache Effects&lt;&#x2F;a&gt;. Knowing a few things about the cache can make a big difference.&lt;&#x2F;li&gt; &lt;&#x2F;ul&gt; </content> </entry>
M blog/index.htmlblog/index.html

@@ -1,4 +1,4 @@

-<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>My Blog</h1><p id=welcome onclick=pls_stop()>Welcome to my blog!<p>Here I occasionally post new entries, mostly tech related. Perhaps it's tips for a new game I'm playing, perhaps it has something to do with FFI, or perhaps I'm fighting the borrow checker (just kidding, I'm over that. Mostly).<hr><ul><li><a href=https://lonami.dev/blog/woce-2/>Writing our own Cheat Engine: Exact Value scanning</a><span class=dim> [mod sw; 'windows, 'rust, 'hacking] </span><li><a href=https://lonami.dev/blog/woce-1/>Writing our own Cheat Engine: Introduction</a><span class=dim> [mod sw; 'windows, 'rust, 'hacking] </span><li><a href=https://lonami.dev/blog/university/>Data Mining, Warehousing and Information Retrieval</a><span class=dim> [mod algos; 'series, 'bigdata, 'databases] </span><li><a href=https://lonami.dev/blog/new-computer/>My new computer</a><span class=dim> [mod hw; 'showoff] </span><li><a href=https://lonami.dev/blog/tips-outpost/>Tips for Outpost</a><span class=dim> [mod games; 'tips] </span><li><a href=https://lonami.dev/blog/ctypes-and-windows/>Python ctypes and Windows</a><span class=dim> [mod sw; 'python, 'ffi, 'windows] </span><li><a href=https://lonami.dev/blog/pixel-dungeon/>Shattered Pixel Dungeon</a><span class=dim> [mod games; 'tips] </span><li><a href=https://lonami.dev/blog/installing-nixos-2/>Installing NixOS, Take 2</a><span class=dim> [mod sw; 'os, 'nixos] </span><li><a href=https://lonami.dev/blog/breaking-ror/>Breaking Risk of Rain</a><span class=dim> [mod games; 'tips] </span><li><a href=https://lonami.dev/blog/world-edit/>WorldEdit Commands</a><span class=dim> [mod games; 'minecraft, 'worldedit, 'tips] </span><li><a href=https://lonami.dev/blog/asyncio/>An Introduction to Asyncio</a><span class=dim> [mod sw; 'python, 'asyncio] </span><li><a href=https://lonami.dev/blog/posts/>Atemporal Blog Posts</a><span class=dim> [mod algos; 'algorithms, 'culture, 'debate, 'foodforthought, 'graphics, 'optimization] </span><li><a href=https://lonami.dev/blog/graphs/>Graphs</a><span class=dim> [mod algos; 'graphs] </span><li><a href=https://lonami.dev/blog/installing-nixos/>Installing NixOS</a><span class=dim> [mod sw; 'os, 'nixos] </span></ul><script> +<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>My Blog</h1><p id=welcome onclick=pls_stop()>Welcome to my blog!<p>Here I occasionally post new entries, mostly tech related. Perhaps it's tips for a new game I'm playing, perhaps it has something to do with FFI, or perhaps I'm fighting the borrow checker (just kidding, I'm over that. Mostly).<hr><ul><li><a href=https://lonami.dev/blog/woce-3/>Writing our own Cheat Engine: Unknown initial value</a><span class=dim> [mod sw; 'windows, 'rust, 'hacking] </span><li><a href=https://lonami.dev/blog/woce-2/>Writing our own Cheat Engine: Exact Value scanning</a><span class=dim> [mod sw; 'windows, 'rust, 'hacking] </span><li><a href=https://lonami.dev/blog/woce-1/>Writing our own Cheat Engine: Introduction</a><span class=dim> [mod sw; 'windows, 'rust, 'hacking] </span><li><a href=https://lonami.dev/blog/university/>Data Mining, Warehousing and Information Retrieval</a><span class=dim> [mod algos; 'series, 'bigdata, 'databases] </span><li><a href=https://lonami.dev/blog/new-computer/>My new computer</a><span class=dim> [mod hw; 'showoff] </span><li><a href=https://lonami.dev/blog/tips-outpost/>Tips for Outpost</a><span class=dim> [mod games; 'tips] </span><li><a href=https://lonami.dev/blog/ctypes-and-windows/>Python ctypes and Windows</a><span class=dim> [mod sw; 'python, 'ffi, 'windows] </span><li><a href=https://lonami.dev/blog/pixel-dungeon/>Shattered Pixel Dungeon</a><span class=dim> [mod games; 'tips] </span><li><a href=https://lonami.dev/blog/installing-nixos-2/>Installing NixOS, Take 2</a><span class=dim> [mod sw; 'os, 'nixos] </span><li><a href=https://lonami.dev/blog/breaking-ror/>Breaking Risk of Rain</a><span class=dim> [mod games; 'tips] </span><li><a href=https://lonami.dev/blog/world-edit/>WorldEdit Commands</a><span class=dim> [mod games; 'minecraft, 'worldedit, 'tips] </span><li><a href=https://lonami.dev/blog/asyncio/>An Introduction to Asyncio</a><span class=dim> [mod sw; 'python, 'asyncio] </span><li><a href=https://lonami.dev/blog/posts/>Atemporal Blog Posts</a><span class=dim> [mod algos; 'algorithms, 'culture, 'debate, 'foodforthought, 'graphics, 'optimization] </span><li><a href=https://lonami.dev/blog/graphs/>Graphs</a><span class=dim> [mod algos; 'graphs] </span><li><a href=https://lonami.dev/blog/installing-nixos/>Installing NixOS</a><span class=dim> [mod sw; 'os, 'nixos] </span></ul><script> const WELCOME_EN = 'Welcome to my blog!' const WELCOME_ES = '¡Bienvenido a mi blog!' const APOLOGIES = "ok sorry i'll stop"
M blog/posts/index.htmlblog/posts/index.html

@@ -1,1 +1,1 @@

-<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Atemporal Blog Posts | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Atemporal Blog Posts</h1><div class=time><p>2018-02-03</div><p>These are some interesting posts and links I've found around the web. I believe they are quite interesting and nice reads, so if you have the time, I encourage you to check some out.<h2 id=algorithms>Algorithms</h2><ul><li>http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/. Image Dithering: Eleven Algorithms and Source Code. What does it mean and how to achieve it?<li>https://cristian.io/post/bloom-filters/. Idempotence layer on bloom filters. What are they and how can they help?<li>https://en.wikipedia.org/wiki/Huffman_coding. Huffman coding. This encoding is a simple yet interesting way of compressing information.<li>https://github.com/mxgmn/WaveFunctionCollapse. Wave Function Collapse. Bitmap & tilemap generation from a single example with the help of ideas from quantum mechanics.<li>https://blog.nelhage.com/2015/02/regular-expression-search-with-suffix-arrays/. Regular Expression Search with Suffix Arrays. A way to efficiently search large amounts of text.</ul><h2 id=culture>Culture</h2><ul><li>https://www.wired.com/story/ideas-joi-ito-robot-overlords/. Why Westerners Fear Robots and the Japanese Do Not. Explains some possible reasons for this case.<li>http://catb.org/~esr/faqs/smart-questions.html. How To Ask Questions The Smart Way. Some bits of hacker culture and amazing tips on how to ask a question.<li>http://apenwarr.ca/log/?m=201809#14. XML, blockchains, and the strange shapes of progress. Some of history about XML and blockchain.<li>https://czep.net/17/legion-of-lobotomized-unices.html. Legion of lobotomized unices. A time where computers are treated a lot more nicely.<li>https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions/. The Expression Problem and its solutions. What is it and what can we do to solve it?<li>http://allendowney.blogspot.com/2015/08/the-inspection-paradox-is-everywhere.html. The Inspection Paradox is Everywhere. Interesting and very common phenomena.<li>https://github.com/ChrisKnott/Algojammer. An experimental code editor for writing algorithms. Contains several links to different tools for reverse debugging.<li>http://habitatchronicles.com/2017/05/what-are-capabilities/. What Are Capabilities? Good ideas with great security implications.<li>https://blog.aurynn.com/2015/12/16-contempt-culture. Contempt Culture. Or why you should not speak crap about your non-favourite programming languages.<li>https://www.lesswrong.com/posts/tscc3e5eujrsEeFN4/well-kept-gardens-die-by-pacifism. Well-Kept Gardens Die By Pacifism. Risks any online community can run into.<li>https://ncase.me/. It's Nicky Case! They make some cool things worth checking out, I really like "we become what we behold".</ul><h2 id=debate>Debate</h2><ul><li>https://steemit.com/opensource/@crell/open-source-is-awful. Open Source is awful. Has some points about why is it bad and how it could improve.<li>http://www.mondo2000.com/2018/01/17/pink-lexical-goop-dark-side-autocorrect/. Pink Lexical Goop: The Dark Side of Autocorrect. It can shape how you think.<li>http://blog.ploeh.dk/2015/08/03/idiomatic-or-idiosyncratic/. Idiomatic or idiosyncratic? Can porting code constructs from other languages have a positive effect?<li>https://gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php. In-depth: Functional programming in C++. Is it useful to bother with functional concepts in a language like C++?<li>https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/. Notes on structured concurrency, or: Go statement considered harmful.<li>https://queue.acm.org/detail.cfm?id=3212479. C Is Not a Low-level Language. Could there be alternative programming models designed for more specialized CPUs?</ul><h2 id=food-for-thought>Food for Thought</h2><ul><li>https://www.hillelwayne.com/post/divide-by-zero/. 1/0 = 0. Explores why it makes sense to redefine mathemathics under some circumstances, and why it is possible to do so.<li>https://jeremykun.com/2018/04/13/for-mathematicians-does-not-mean-equality/. For mathematicians, = does not mean equality. What other definitions does the equal sign have?<li>https://www.lesswrong.com/posts/2MD3NMLBPCqPfnfre/cached-thoughts. Cached Thoughts. How is it possible that our brains work at all?<li>http://tonsky.me/blog/disenchantment/. Software disenchantment. Faster hardware and slower software is a trend. <ul><li>https://blackhole12.com/blog/software-engineering-is-bad-but-it-s-not-that-bad/. Software Engineering Is Bad, But That's Not Why. This post has some good counterpoints to Software disenchantment.</ul><li>http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/. What Color is Your Function? Spoiler: can we approach asynchronous IO better?<li>https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5. I'm harvesting credit card numbers and passwords from your site. A word of warning when mindlessly adding dependencies.<li>https://medium.com/message/everything-is-broken-81e5f33a24e1. Everything Is Broken. Some of the (probable) truths about our world.</ul><h2 id=funny>Funny</h2><ul><li>http://thedailywtf.com/articles/We-Use-BobX. We Use BobX. BobX.<li>http://thedailywtf.com/articles/the-inner-json-effect. The Inner JSON Effect. For some reason, custom languages are in.<li>https://thedailywtf.com/articles/exponential-backup. Exponential Backup. Far better than git.<li>https://thedailywtf.com/articles/ITAPPMONROBOT. ITAPPMONROBOT. Solving software problems with hardware.<li>https://thedailywtf.com/articles/a-tapestry-of-threads. A Tapestry of Threads.More threads must mean faster code, right?<li>https://medium.com/commitlog/a-brief-totally-accurate-history-of-programming-languages-cd93ec806124. A Brief Totally Accurate History Of Programming Languages. Don't take offense for it!</ul><h2 id=graphics>Graphics</h2><ul><li>http://shaunlebron.github.io/visualizing-projections/. Visualizing Projections. Small post about different projection methods.<li>http://www.iquilezles.org/www/index.htm. A <em>lot</em> of useful and quality articles regarding computer graphics.</ul><h2 id=history>History</h2><ul><li>https://twobithistory.org/2018/08/18/ada-lovelace-note-g.html. What Did Ada Lovelace's Program Actually Do?. And other characters that took part in the beginning's of programming.<li>https://chrisdown.name/2018/01/02/in-defence-of-swap.html. In defence of swap: common misconceptions. Swap is still an useful concept.<li>https://www.pacifict.com/Story/. The Graphing Calculator Story. A great classic Apple tale.<li>https://twobithistory.org/2018/10/14/lisp.html. How Lisp Became God's Own Programming Language. Lisp as a foundational programming language.</ul><h2 id=motivational>Motivational</h2><ul><li>https://www.joelonsoftware.com/2002/01/06/fire-and-motion/. Fire And Motion. What does actually take to get things done?<li>https://realmensch.org/2017/08/25/the-parable-of-the-two-programmers/. The Parable of the Two Programmers. This tale is about two different types of programmer and their respective endings in a company, illustrating how the one you wouldn't expect to actually ends in a better situation.<li>https://byorgey.wordpress.com/2018/05/06/conversations-with-a-six-year-old-on-functional-programming/. Conversations with a six-year-old on functional programming. Little kids today can be really interested in technological topics.<li>https://bulletproofmusician.com/how-many-hours-a-day-should-you-practice/. How Many Hours a Day Should You Practice?. While the article is about music, it applies to any other areas.<li>http://nathanmarz.com/blog/suffering-oriented-programming.html. Suffering-oriented programming. A possibly new approach on how you could tackle your new projects.<li>https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/. Things You Should Never Do, Part I. There is no need to rewrite your code.</ul><h2 id=optimization>Optimization</h2><ul><li>http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html. What Every C Programmer Should Know About Undefined Behavior #1/3. Explains what undefined behaviour is and why it makes sense.<li>http://ridiculousfish.com/blog/posts/labor-of-division-episode-i.html. Labor of Division (Episode I). Some tricks to divide without division.<li>http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html. A Great Old-Timey Game-Programming Hack. Abusing instructions to make games playable even on the slowest hardware.<li>https://web.archive.org/web/20191213224640/https://people.eecs.berkeley.edu/~sangjin/2012/12/21/epoll-vs-kqueue.html. Scalable Event Multiplexing: epoll vs kqueue. How good OS primitives can really help performance and scability.<li>https://adamdrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html. Command-line Tools can be 235x Faster than your Hadoop Cluster. Or how to use the right tool for the right job.<li>https://nullprogram.com/blog/2018/05/27/. When FFI Function Calls Beat Native C. How lua beat C at it and the explanation behind it.<li>http://igoro.com/archive/gallery-of-processor-cache-effects/. Gallery of Processor Cache Effects. Knowing a few things about the cache can make a big difference.</ul></main><footer><div><p>Share your thoughts, or simply come hang with me <a href=https://t.me/LonamiWebs><img src=/img/telegram.svg alt=Telegram></a> <a href=mailto:totufals@hotmail.com><img src=/img/mail.svg alt=Mail></a></div></footer></article><p class=abyss>Glaze into the abyss… Oh hi there!+<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Atemporal Blog Posts | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Atemporal Blog Posts</h1><div class=time><p>2018-02-03<p>last updated 2021-02-19</div><p>These are some interesting posts and links I've found around the web. I believe they are quite interesting and nice reads, so if you have the time, I encourage you to check some out.<h2 id=algorithms>Algorithms</h2><ul><li><a href=http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/>Image Dithering: Eleven Algorithms and Source Code</a>. What does it mean and how to achieve it?<li><a href=https://cristian.io/post/bloom-filters/>Idempotence layer on bloom filters</a>. What are they and how can they help?<li><a href=https://en.wikipedia.org/wiki/Huffman_coding>Huffman coding</a>. This encoding is a simple yet interesting way of compressing information.<li><a href=https://github.com/mxgmn/WaveFunctionCollapse>Wave Function Collapse</a>. Bitmap & tilemap generation from a single example with the help of ideas from quantum mechanics.<li><a href=https://blog.nelhage.com/2015/02/regular-expression-search-with-suffix-arrays/>Regular Expression Search with Suffix Arrays</a>. A way to efficiently search large amounts of text.</ul><h2 id=culture>Culture</h2><ul><li><a href=https://www.wired.com/story/ideas-joi-ito-robot-overlords/>Why Westerners Fear Robots and the Japanese Do Not</a>. Explains some possible reasons for this case.<li><a href=http://catb.org/%7Eesr/faqs/smart-questions.html>How To Ask Questions The Smart Way</a>. Some bits of hacker culture and amazing tips on how to ask a question.<li><a href=http://apenwarr.ca/log/?m=201809#14>XML, blockchains, and the strange shapes of progress</a>. Some of history about XML and blockchain.<li><a href=https://czep.net/17/legion-of-lobotomized-unices.html>Legion of lobotomized unices</a>. A time where computers are treated a lot more nicely.<li><a href=https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions/>The Expression Problem and its solutions</a>. What is it and what can we do to solve it?<li><a href=http://allendowney.blogspot.com/2015/08/the-inspection-paradox-is-everywhere.html>The Inspection Paradox is Everywhere</a>. Interesting and very common phenomena.<li><a href=https://github.com/ChrisKnott/Algojammer>An experimental code editor for writing algorithms</a>. Contains several links to different tools for reverse debugging.<li><a href=http://habitatchronicles.com/2017/05/what-are-capabilities/>What Are Capabilities?</a> Good ideas with great security implications.<li><a href=https://blog.aurynn.com/2015/12/16-contempt-culture>Contempt Culture</a>. Or why you should not speak crap about your non-favourite programming languages.<li><a href=https://www.lesswrong.com/posts/tscc3e5eujrsEeFN4/well-kept-gardens-die-by-pacifism>Well-Kept Gardens Die By Pacifism</a>. Risks any online community can run into.<li><a href=https://ncase.me/>It's Nicky Case!</a> They make some cool things worth checking out, I really like "we become what we behold".</ul><h2 id=debate>Debate</h2><ul><li><a href=https://steemit.com/opensource/@crell/open-source-is-awful>Open Source is awful</a>. Has some points about why is it bad and how it could improve.<li><a href=http://www.mondo2000.com/2018/01/17/pink-lexical-goop-dark-side-autocorrect/>Pink Lexical Goop: The Dark Side of Autocorrect</a>. It can shape how you think.<li><a href=http://blog.ploeh.dk/2015/08/03/idiomatic-or-idiosyncratic/>Idiomatic or idiosyncratic?</a> Can porting code constructs from other languages have a positive effect?<li><a href=https://gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php>In-depth: Functional programming in C++</a>. Is it useful to bother with functional concepts in a language like C++?<li><a href=https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/>Notes on structured concurrency, or: Go statement considered harmful</a>.<li><a href=https://queue.acm.org/detail.cfm?id=3212479>C Is Not a Low-level Language</a>. Could there be alternative programming models designed for more specialized CPUs?</ul><h2 id=food-for-thought>Food for Thought</h2><ul><li><a href=https://www.hillelwayne.com/post/divide-by-zero/>1/0 = 0</a>. Explores why it makes sense to redefine mathemathics under some circumstances, and why it is possible to do so.<li><a href=https://jeremykun.com/2018/04/13/for-mathematicians-does-not-mean-equality/>For mathematicians, = does not mean equality</a>. What other definitions does the equal sign have?<li><a href=https://www.lesswrong.com/posts/2MD3NMLBPCqPfnfre/cached-thoughts>Cached Thoughts</a>. How is it possible that our brains work at all?<li><a href=http://tonsky.me/blog/disenchantment/>Software disenchantment</a>. Faster hardware and slower software is a trend. <ul><li><a href=https://blackhole12.com/blog/software-engineering-is-bad-but-it-s-not-that-bad/>Software Engineering Is Bad, But That's Not Why</a>. This post has some good counterpoints to Software disenchantment.</ul><li><a href=http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/>What Color is Your Function?</a>. Spoiler: can we approach asynchronous IO better?<li><a href=https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5>I'm harvesting credit card numbers and passwords from your site</a>. A word of warning when mindlessly adding dependencies.<li><a href=https://medium.com/message/everything-is-broken-81e5f33a24e1>Everything Is Broken</a>. Some of the (probable) truths about our world.<li><a href=http://johnsalvatier.org/blog/2017/reality-has-a-surprising-amount-of-detail>Reality has a surprising amount of detail</a>.</ul><h2 id=funny>Funny</h2><ul><li><a href=http://thedailywtf.com/articles/We-Use-BobX>We Use BobX</a>. BobX.<li><a href=http://thedailywtf.com/articles/the-inner-json-effect>The Inner JSON Effect</a>. For some reason, custom languages are in.<li><a href=https://thedailywtf.com/articles/exponential-backup>Exponential Backup</a>. Far better than git.<li><a href=https://thedailywtf.com/articles/ITAPPMONROBOT>ITAPPMONROBOT</a>. Solving software problems with hardware.<li><a href=https://thedailywtf.com/articles/a-tapestry-of-threads>A Tapestry of Threads</a>. More threads must mean faster code, right?<li><a href=https://medium.com/commitlog/a-brief-totally-accurate-history-of-programming-languages-cd93ec806124>A Brief Totally Accurate History Of Programming Languages</a>. Don't take offense for it!</ul><h2 id=graphics>Graphics</h2><ul><li><a href=http://shaunlebron.github.io/visualizing-projections/>Visualizing Projections</a>. Small post about different projection methods.<li><a href=http://www.iquilezles.org/www/index.htm>Inigo Quilez :: fractals, computer graphics, mathematics, shaders, demoscene and more</a> A <em>lot</em> of useful and quality articles regarding computer graphics.</ul><h2 id=history>History</h2><ul><li><a href=https://twobithistory.org/2018/08/18/ada-lovelace-note-g.html>What Did Ada Lovelace's Program Actually Do?</a>. And other characters that took part in the beginning's of programming.<li><a href=https://chrisdown.name/2018/01/02/in-defence-of-swap.html>In defence of swap: common misconceptions</a>. Swap is still an useful concept.<li><a href=https://www.pacifict.com/Story/>The Graphing Calculator Story</a>. A great classic Apple tale.<li><a href=https://twobithistory.org/2018/10/14/lisp.html>How Lisp Became God's Own Programming Language</a>. Lisp as a foundational programming language.</ul><h2 id=motivational>Motivational</h2><ul><li><a href=https://www.joelonsoftware.com/2002/01/06/fire-and-motion/>Fire And Motion</a>. What does actually take to get things done?<li><a href=https://realmensch.org/2017/08/25/the-parable-of-the-two-programmers/>The Parable of the Two Programmers</a>. This tale is about two different types of programmer and their respective endings in a company, illustrating how the one you wouldn't expect to actually ends in a better situation.<li><a href=https://byorgey.wordpress.com/2018/05/06/conversations-with-a-six-year-old-on-functional-programming/>Conversations with a six-year-old on functional programming</a>. Little kids today can be really interested in technological topics.<li><a href=https://bulletproofmusician.com/how-many-hours-a-day-should-you-practice/>How Many Hours a Day Should You Practice?</a>. While the article is about music, it applies to any other areas.<li><a href=http://nathanmarz.com/blog/suffering-oriented-programming.html>Suffering-oriented programming</a>. A possibly new approach on how you could tackle your new projects.<li><a href=https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/>Things You Should Never Do, Part I</a>. There is no need to rewrite your code.</ul><h2 id=optimization>Optimization</h2><ul><li><a href=http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html>What Every C Programmer Should Know About Undefined Behavior #1/3</a>. Explains what undefined behaviour is and why it makes sense.<li><a href=http://ridiculousfish.com/blog/posts/labor-of-division-episode-i.html>Labor of Division (Episode I)</a>. Some tricks to divide without division.<li><a href=http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html>A Great Old-Timey Game-Programming Hack</a>. Abusing instructions to make games playable even on the slowest hardware.<li><a href=https://web.archive.org/web/20191213224640/https://people.eecs.berkeley.edu/%7Esangjin/2012/12/21/epoll-vs-kqueue.html>Scalable Event Multiplexing: epoll vs kqueue</a>. How good OS primitives can really help performance and scability.<li><a href=https://adamdrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html>Command-line Tools can be 235x Faster than your Hadoop Cluster</a>. Or how to use the right tool for the right job.<li><a href=https://nullprogram.com/blog/2018/05/27/>When FFI Function Calls Beat Native C</a>. How lua beat C at it and the explanation behind it.<li><a href=http://igoro.com/archive/gallery-of-processor-cache-effects/>Gallery of Processor Cache Effects</a>. Knowing a few things about the cache can make a big difference.</ul></main><footer><div><p>Share your thoughts, or simply come hang with me <a href=https://t.me/LonamiWebs><img src=/img/telegram.svg alt=Telegram></a> <a href=mailto:totufals@hotmail.com><img src=/img/mail.svg alt=Mail></a></div></footer></article><p class=abyss>Glaze into the abyss… Oh hi there!
M blog/woce-1/index.htmlblog/woce-1/index.html

@@ -1,4 +1,4 @@

-<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Writing our own Cheat Engine: Introduction | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Writing our own Cheat Engine: Introduction</h1><div class=time><p>2021-02-07<p>last updated 2021-02-16</div><p>This is part 1 on the <em>Writing our own Cheat Engine</em> series:<ul><li>Part 1: Introduction<li><a href=/blog/woce-2>Part 2: Exact Value scanning</a></ul><p><a href=https://cheatengine.org/>Cheat Engine</a> is a tool designed to modify single player games and contains other useful tools within itself that enable its users to debug games or other applications. It comes with a memory scanner, (dis)assembler, inspection tools and a handful other things. In this series, we will be writing our own tiny Cheat Engine capable of solving all steps of the tutorial, and diving into how it all works underneath.<p>Needless to say, we're doing this for private and educational purposes only. One has to make sure to not violate the EULA or ToS of the specific application we're attaching to. This series, much like cheatengine.org, does not condone the illegal use of the code shared.<p>Cheat Engine is a tool for Windows, so we will be developing for Windows as well. However, you can also <a href=https://stackoverflow.com/q/12977179/4759433>read memory from Linux-like systems</a>. <a href=https://github.com/scanmem/scanmem>GameConqueror</a> is a popular alternative to Cheat Engine on Linux systems, so if you feel adventurous, you could definitely follow along too! The techniques shown in this series apply regardless of how we read memory from a process. You will learn a fair bit about doing FFI in Rust too.<p>We will be developing the application in Rust, because it enables us to interface with the Windows API easily, is memory safe (as long as we're careful with <code>unsafe</code>!), and is speedy (we will need this for later steps in the Cheat Engine tutorial). You could use any language of your choice though. For example, <a href=https://lonami.dev/blog/ctypes-and-windows/>Python also makes it relatively easy to use the Windows API</a>. You don't need to be a Rust expert to follow along, but this series assumes some familiarity with C-family languages. Slightly advanced concepts like the use of <code>unsafe</code> or the <code>MaybeUninit</code> type will be briefly explained. What a <code>fn</code> is or what <code>let</code> does will not be explained.<p><a href=https://github.com/cheat-engine/cheat-engine/>Cheat Engine's source code</a> is mostly written in Pascal and C. And it's <em>a lot</em> of code, with a very flat project structure, and files ranging in the thousand lines of code each. It's daunting<sup class=footnote-reference><a href=#1>1</a></sup>. It's a mature project, with a lot of knowledge encoded in the code base, and a lot of features like distributed scanning or an entire disassembler. Unfortunately, there's not a lot of comments. For these reasons, I'll do some guesswork when possible as to how it's working underneath, rather than actually digging into what Cheat Engine is actually doing.<p>With that out of the way, let's get started!<h2 id=welcome-to-the-cheat-engine-tutorial>Welcome to the Cheat Engine Tutorial</h2><details open><summary>Cheat Engine Tutorial: Step 1</summary> <blockquote><p>This tutorial will teach you the basics of cheating in video games. It will also show you foundational aspects of using Cheat Engine (or CE for short). Follow the steps below to get started.<ol><li>Open Cheat Engine if it currently isn't running.<li>Click on the "Open Process" icon (it's the top-left icon with the computer on it, below "File".).<li>With the Process List window now open, look for this tutorial's process in the list. It will look something like > "00001F98-Tutorial-x86_64.exe" or "0000047C-Tutorial-i386.exe". (The first 8 numbers/letters will probably be different.)<li>Once you've found the process, click on it to select it, then click the "Open" button. (Don't worry about all the > other buttons right now. You can learn about them later if you're interested.)</ol><p>Congratulations! If you did everything correctly, the process window should be gone with Cheat Engine now attached to the > tutorial (you will see the process name towards the top-center of CE).<p>Click the "Next" button below to continue, or fill in the password and click the "OK" button to proceed to that step.)<p>If you're having problems, simply head over to forum.cheatengine.org, then click on "Tutorials" to view beginner-friendly > guides!</blockquote></details><h2 id=enumerating-processes>Enumerating processes</h2><p>Our first step is attaching to the process we want to work with. But we need a way to find that process in the first place! Having to open the task manager, look for the process we care about, noting down the process ID (PID), and slapping it in the source code is not satisfying at all. Instead, let's enumerate all the processes from within the program, and let the user select one by typing its name.<p>From a quick <a href=https://ddg.gg/winapi%20enumerate%20all%20processes>DuckDuckGo search</a>, we find an official tutorial for <a href=https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes>Enumerating All Processes</a>, which leads to the <a href=https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses><code>EnumProcesses</code></a> call. Cool! Let's slap in the <a href=https://crates.io/crates/winapi><code>winapi</code></a> crate on <code>Cargo.toml</code>, because I don't want to write all the definitions by myself:<pre><code class=language-toml data-lang=toml>[dependencies] +<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Writing our own Cheat Engine: Introduction | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Writing our own Cheat Engine: Introduction</h1><div class=time><p>2021-02-07<p>last updated 2021-02-19</div><p>This is part 1 on the <em>Writing our own Cheat Engine</em> series:<ul><li>Part 1: Introduction<li><a href=/blog/woce-2>Part 2: Exact Value scanning</a><li><a href=/blog/woce-3>Part 3: Unknown initial value</a></ul><p><a href=https://cheatengine.org/>Cheat Engine</a> is a tool designed to modify single player games and contains other useful tools within itself that enable its users to debug games or other applications. It comes with a memory scanner, (dis)assembler, inspection tools and a handful other things. In this series, we will be writing our own tiny Cheat Engine capable of solving all steps of the tutorial, and diving into how it all works underneath.<p>Needless to say, we're doing this for private and educational purposes only. One has to make sure to not violate the EULA or ToS of the specific application we're attaching to. This series, much like cheatengine.org, does not condone the illegal use of the code shared.<p>Cheat Engine is a tool for Windows, so we will be developing for Windows as well. However, you can also <a href=https://stackoverflow.com/q/12977179/4759433>read memory from Linux-like systems</a>. <a href=https://github.com/scanmem/scanmem>GameConqueror</a> is a popular alternative to Cheat Engine on Linux systems, so if you feel adventurous, you could definitely follow along too! The techniques shown in this series apply regardless of how we read memory from a process. You will learn a fair bit about doing FFI in Rust too.<p>We will be developing the application in Rust, because it enables us to interface with the Windows API easily, is memory safe (as long as we're careful with <code>unsafe</code>!), and is speedy (we will need this for later steps in the Cheat Engine tutorial). You could use any language of your choice though. For example, <a href=https://lonami.dev/blog/ctypes-and-windows/>Python also makes it relatively easy to use the Windows API</a>. You don't need to be a Rust expert to follow along, but this series assumes some familiarity with C-family languages. Slightly advanced concepts like the use of <code>unsafe</code> or the <code>MaybeUninit</code> type will be briefly explained. What a <code>fn</code> is or what <code>let</code> does will not be explained.<p><a href=https://github.com/cheat-engine/cheat-engine/>Cheat Engine's source code</a> is mostly written in Pascal and C. And it's <em>a lot</em> of code, with a very flat project structure, and files ranging in the thousand lines of code each. It's daunting<sup class=footnote-reference><a href=#1>1</a></sup>. It's a mature project, with a lot of knowledge encoded in the code base, and a lot of features like distributed scanning or an entire disassembler. Unfortunately, there's not a lot of comments. For these reasons, I'll do some guesswork when possible as to how it's working underneath, rather than actually digging into what Cheat Engine is actually doing.<p>With that out of the way, let's get started!<h2 id=welcome-to-the-cheat-engine-tutorial>Welcome to the Cheat Engine Tutorial</h2><details open><summary>Cheat Engine Tutorial: Step 1</summary> <blockquote><p>This tutorial will teach you the basics of cheating in video games. It will also show you foundational aspects of using Cheat Engine (or CE for short). Follow the steps below to get started.<ol><li>Open Cheat Engine if it currently isn't running.<li>Click on the "Open Process" icon (it's the top-left icon with the computer on it, below "File".).<li>With the Process List window now open, look for this tutorial's process in the list. It will look something like > "00001F98-Tutorial-x86_64.exe" or "0000047C-Tutorial-i386.exe". (The first 8 numbers/letters will probably be different.)<li>Once you've found the process, click on it to select it, then click the "Open" button. (Don't worry about all the > other buttons right now. You can learn about them later if you're interested.)</ol><p>Congratulations! If you did everything correctly, the process window should be gone with Cheat Engine now attached to the > tutorial (you will see the process name towards the top-center of CE).<p>Click the "Next" button below to continue, or fill in the password and click the "OK" button to proceed to that step.)<p>If you're having problems, simply head over to forum.cheatengine.org, then click on "Tutorials" to view beginner-friendly > guides!</blockquote></details><h2 id=enumerating-processes>Enumerating processes</h2><p>Our first step is attaching to the process we want to work with. But we need a way to find that process in the first place! Having to open the task manager, look for the process we care about, noting down the process ID (PID), and slapping it in the source code is not satisfying at all. Instead, let's enumerate all the processes from within the program, and let the user select one by typing its name.<p>From a quick <a href=https://ddg.gg/winapi%20enumerate%20all%20processes>DuckDuckGo search</a>, we find an official tutorial for <a href=https://docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes>Enumerating All Processes</a>, which leads to the <a href=https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses><code>EnumProcesses</code></a> call. Cool! Let's slap in the <a href=https://crates.io/crates/winapi><code>winapi</code></a> crate on <code>Cargo.toml</code>, because I don't want to write all the definitions by myself:<pre><code class=language-toml data-lang=toml>[dependencies] winapi = { version = "0.3.9", features = ["psapi"] } </code></pre><p>Because <a href=https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses><code>EnumProcesses</code></a> is in <code>Psapi.h</code> (you can see this in the online page of its documentation), we know we'll need the <code>psapi</code> crate feature. Another option is to search for it in the <a href=https://docs.rs/winapi/><code>winapi</code> documentation</a> and noting down the parent module where its stored.<p>The documentation for the method has the following remark:<blockquote><p>It is a good idea to use a large array, because it is hard to predict how many processes there will be at the time you call <strong>EnumProcesses</strong>.</blockquote><p><em>Sidenote: reading the documentation for the methods we'll use from the Windows API is extremely important. There's a lot of gotchas involved, so we need to make sure we're extra careful.</em><p>1024 is a pretty big number, so let's go with that:<pre><code class=language-rust data-lang=rust>use std::io; use std::mem;
M blog/woce-2/index.htmlblog/woce-2/index.html

@@ -1,4 +1,4 @@

-<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Writing our own Cheat Engine: Exact Value scanning | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Writing our own Cheat Engine: Exact Value scanning</h1><div class=time><p>2021-02-12<p>last updated 2021-02-16</div><p>This is part 2 on the <em>Writing our own Cheat Engine</em> series:<ul><li><a href=/blog/woce-1>Part 1: Introduction</a> (start here if you're new to the series!)<li>Part 2: Exact Value scanning</ul><p>In the introduction, we spent a good deal of time enumerating all running processes just so we could find out the pid we cared about. With the pid now in our hands, we can do pretty much anything to its corresponding process.<p>It's now time to read the process' memory and write to it. If our process was a single-player game, this would enable us to do things like setting a very high value on the player's current health pool, making us invincible. This technique will often not work for multi-player games, because the server likely knows your true current health (the most you could probably do is make the client render an incorrect value). However, if the server is crappy and it trusts the client, then you're still free to mess around with your current health.<p>Even if we don't want to write to the process' memory, reading is still very useful. Maybe you could enhance your experience by making a custom overlay that displays useful information, or something that makes noise if it detects the life is too low, or even simulating a keyboard event to automatically recover some mana when you're running low.<p>Be warned about anti-cheat systems. Anything beyond a basic game is likely to have some protection measures in place, making the analysis more difficult (perhaps the values are scrambled in memory), or even pinging the server if it detects something fishy.<p><strong>I am not responsible for any bans!</strong> Use your brain before messing with online games, and don't ruin the fun for everyone else. If you get caught for cheating, I don't want to know about it.<p>Now that all <a href=https://www.urbandictionary.com/define.php?term=script%20kiddie>script kiddies</a> have left the room, let's proceed with the post.<h2 id=exact-value-scanning>Exact Value scanning</h2><details open><summary>Cheat Engine Tutorial: Step 2</summary> <blockquote><p>Now that you have opened the tutorial with Cheat Engine let's get on with the next step.<p>You can see at the bottom of this window is the text Health: xxx. Each time you click 'Hit me' your health gets decreased.<p>To get to the next step you have to find this value and change it to 1000<p>To find the value there are different ways, but I'll tell you about the easiest, 'Exact Value': First make sure value type is set to at least 2-bytes or 4-bytes. 1-byte will also work, but you'll run into an easy to fix problem when you've found the address and want to change it. The 8-byte may perhaps works if the bytes after the address are 0, but I wouldn't take the bet. Single, double, and the other scans just don't work, because they store the value in a different way.<p>When the value type is set correctly, make sure the scantype is set to 'Exact Value'. Then fill in the number your health is in the value box. And click 'First Scan'. After a while (if you have a extremely slow pc) the scan is done and the results are shown in the list on the left<p>If you find more than 1 address and you don't know for sure which address it is, click 'Hit me', fill in the new health value into the value box, and click 'Next Scan'. Repeat this until you're sure you've found it. (that includes that there's only 1 address in the list.....)<p>Now double click the address in the list on the left. This makes the address pop-up in the list at the bottom, showing you the current value. Double click the value, (or select it and press enter), and change the value to 1000.<p>If everything went ok the next button should become enabled, and you're ready for the next step.<p>Note: If you did anything wrong while scanning, click "New Scan" and repeat the scanning again. Also, try playing around with the value and click 'hit me'</blockquote></details><h2 id=our-first-scan>Our First Scan</h2><p>The Cheat Engine tutorial talks about "value types" and "scan types" like "exact value".<p>The <strong>value types</strong> will help us narrow down <em>what</em> we're looking for. For example, the integer type <code>i32</code> is represented in memory as 32 bits, or 4 bytes. However, <code>f32</code> is <em>also</em> represented by 4 bytes, and so is <code>u32</code>. Or perhaps the 4 bytes represent RGBA values of a color! So any 4 bytes in memory can be interpreted in many ways, and it's up to us to decide which way we interpret the bytes in.<p>When programming, numbers which are 32-bit wide are common, as they're a good (and fast) size to work with. Scanning for this type is often a good bet. For positive numbers, <code>i32</code> is represented the same as <code>u32</code> in memory, so even if the value turns out to not be signed, the scan is likely to work. Focusing on <code>i32</code> will save us from scanning for <code>f32</code> or even other types, like interpreting 8 bytes for <code>i64</code>, <code>f64</code>, or less bytes like <code>i16</code>.<p>The <strong>scan types</strong> will help us narrow down <em>how</em> we're looking for a value. Scanning for an exact value means what you think it does: interpret all 4 bytes in the process' memory as our value type, and check if they exactly match our value. This will often yield a lot of candidates, but it will be enough to get us started. Variations of the exact scan include checking for all values below a threshold, above, in between, or even just… unknown.<p>What's the point of scanning for unknown values if <em>everything</em> in memory is unknown? Sometimes you don't have a concrete value. Maybe your health pool is a bar and it nevers tell you how much health you actually have, just a visual indicator of your percentage left, even if the health is not stored as a percentage. As we will find later on, scanning for unknown values is more useful than it might appear at first.<p>We can access the memory of our own program by guessing random pointers and trying to read from them. But Windows isolates the memory of each program, so no pointer we could ever guess will let us read from the memory of another process. Luckily for us, searching for "read process memory winapi" leads us to the <a href=https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory><code>ReadProcessMemory</code></a> function. Spot on.<pre><code class=language-rust data-lang=rust>pub fn read_memory(&self, addr: usize, n: usize) -> io::Result&LTVec&LTu8>> { +<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Writing our own Cheat Engine: Exact Value scanning | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Writing our own Cheat Engine: Exact Value scanning</h1><div class=time><p>2021-02-12<p>last updated 2021-02-19</div><p>This is part 2 on the <em>Writing our own Cheat Engine</em> series:<ul><li><a href=/blog/woce-1>Part 1: Introduction</a> (start here if you're new to the series!)<li>Part 2: Exact Value scanning<li><a href=/blog/woce-3>Part 3: Unknown initial value</a></ul><p>In the introduction, we spent a good deal of time enumerating all running processes just so we could find out the pid we cared about. With the pid now in our hands, we can do pretty much anything to its corresponding process.<p>It's now time to read the process' memory and write to it. If our process was a single-player game, this would enable us to do things like setting a very high value on the player's current health pool, making us invincible. This technique will often not work for multi-player games, because the server likely knows your true current health (the most you could probably do is make the client render an incorrect value). However, if the server is crappy and it trusts the client, then you're still free to mess around with your current health.<p>Even if we don't want to write to the process' memory, reading is still very useful. Maybe you could enhance your experience by making a custom overlay that displays useful information, or something that makes noise if it detects the life is too low, or even simulating a keyboard event to automatically recover some mana when you're running low.<p>Be warned about anti-cheat systems. Anything beyond a basic game is likely to have some protection measures in place, making the analysis more difficult (perhaps the values are scrambled in memory), or even pinging the server if it detects something fishy.<p><strong>I am not responsible for any bans!</strong> Use your brain before messing with online games, and don't ruin the fun for everyone else. If you get caught for cheating, I don't want to know about it.<p>Now that all <a href=https://www.urbandictionary.com/define.php?term=script%20kiddie>script kiddies</a> have left the room, let's proceed with the post.<h2 id=exact-value-scanning>Exact Value scanning</h2><details open><summary>Cheat Engine Tutorial: Step 2</summary> <blockquote><p>Now that you have opened the tutorial with Cheat Engine let's get on with the next step.<p>You can see at the bottom of this window is the text Health: xxx. Each time you click 'Hit me' your health gets decreased.<p>To get to the next step you have to find this value and change it to 1000<p>To find the value there are different ways, but I'll tell you about the easiest, 'Exact Value': First make sure value type is set to at least 2-bytes or 4-bytes. 1-byte will also work, but you'll run into an easy to fix problem when you've found the address and want to change it. The 8-byte may perhaps works if the bytes after the address are 0, but I wouldn't take the bet. Single, double, and the other scans just don't work, because they store the value in a different way.<p>When the value type is set correctly, make sure the scantype is set to 'Exact Value'. Then fill in the number your health is in the value box. And click 'First Scan'. After a while (if you have a extremely slow pc) the scan is done and the results are shown in the list on the left<p>If you find more than 1 address and you don't know for sure which address it is, click 'Hit me', fill in the new health value into the value box, and click 'Next Scan'. Repeat this until you're sure you've found it. (that includes that there's only 1 address in the list.....)<p>Now double click the address in the list on the left. This makes the address pop-up in the list at the bottom, showing you the current value. Double click the value, (or select it and press enter), and change the value to 1000.<p>If everything went ok the next button should become enabled, and you're ready for the next step.<p>Note: If you did anything wrong while scanning, click "New Scan" and repeat the scanning again. Also, try playing around with the value and click 'hit me'</blockquote></details><h2 id=our-first-scan>Our First Scan</h2><p>The Cheat Engine tutorial talks about "value types" and "scan types" like "exact value".<p>The <strong>value types</strong> will help us narrow down <em>what</em> we're looking for. For example, the integer type <code>i32</code> is represented in memory as 32 bits, or 4 bytes. However, <code>f32</code> is <em>also</em> represented by 4 bytes, and so is <code>u32</code>. Or perhaps the 4 bytes represent RGBA values of a color! So any 4 bytes in memory can be interpreted in many ways, and it's up to us to decide which way we interpret the bytes in.<p>When programming, numbers which are 32-bit wide are common, as they're a good (and fast) size to work with. Scanning for this type is often a good bet. For positive numbers, <code>i32</code> is represented the same as <code>u32</code> in memory, so even if the value turns out to not be signed, the scan is likely to work. Focusing on <code>i32</code> will save us from scanning for <code>f32</code> or even other types, like interpreting 8 bytes for <code>i64</code>, <code>f64</code>, or less bytes like <code>i16</code>.<p>The <strong>scan types</strong> will help us narrow down <em>how</em> we're looking for a value. Scanning for an exact value means what you think it does: interpret all 4 bytes in the process' memory as our value type, and check if they exactly match our value. This will often yield a lot of candidates, but it will be enough to get us started. Variations of the exact scan include checking for all values below a threshold, above, in between, or even just… unknown.<p>What's the point of scanning for unknown values if <em>everything</em> in memory is unknown? Sometimes you don't have a concrete value. Maybe your health pool is a bar and it nevers tell you how much health you actually have, just a visual indicator of your percentage left, even if the health is not stored as a percentage. As we will find later on, scanning for unknown values is more useful than it might appear at first.<p>We can access the memory of our own program by guessing random pointers and trying to read from them. But Windows isolates the memory of each program, so no pointer we could ever guess will let us read from the memory of another process. Luckily for us, searching for "read process memory winapi" leads us to the <a href=https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory><code>ReadProcessMemory</code></a> function. Spot on.<pre><code class=language-rust data-lang=rust>pub fn read_memory(&self, addr: usize, n: usize) -> io::Result&LTVec&LTu8>> { todo!() } </code></pre><p>Much like trying to dereference a pointer pointing to released memory or even null, reading from an arbitrary address can fail for the same reasons (and more). We will want to signal this with <code>io::Result</code>. It's funny to note that, even though we're doing something that seems wildly unsafe (reading arbitrary memory, even if the other process is mutating it at the same time), the function is perfectly safe. If we cannot read something, it will return <code>Err</code>, but if it succeeds, it has taken a snapshot of the memory of the process, and the returned value will be correctly initialized.<p>The function will be defined inside our <code>impl Process</code>, since it conveniently holds an open handle to the process in question. It takes <code>&self</code>, because we do not need to mutate anything in the <code>Process</code> instance. After adding the <code>memoryapi</code> feature to <code>Cargo.toml</code>, we can perform the call:<pre><code class=language-rust data-lang=rust>let mut buffer = Vec::&LTu8>::with_capacity(n);

@@ -216,7 +216,7 @@ let target: i32 = ...;

let target = target.to_ne_bytes(); locations.retain(...); } -</code></pre><h2 id=modifying-memory>Modifying memory</h2><p>Now that we have very likely locations pointing to our current health in memory, all that's left is writing our new desired value to gain infinite health<sup class=footnote-reference><a href=#9>9</a></sup>. Much like there's a call to <code>ReadProcessMemory</code>, there's a different one to <a href=https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory><code>WriteProcessMemory</code></a>. Its usage is straightforward:<pre><code class=language-rust data-lang=rust>pub fn write_memory(&self, addr: usize, value: &[u8]) -> io::Result&LTusize> { +</code></pre><h2 id=modifying-memory>Modifying memory</h2><p>Now that we have very likely locations pointing to our current health in memory, all that's left is writing our new desired value to gain infinite health<sup class=footnote-reference><a href=#9>9</a></sup>. Much like how we're able to read memory with <code>ReadProcessMemory</code>, we can write to it with <a href=https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory><code>WriteProcessMemory</code></a>. Its usage is straightforward:<pre><code class=language-rust data-lang=rust>pub fn write_memory(&self, addr: usize, value: &[u8]) -> io::Result&LTusize> { let mut written = 0; // SAFETY: the input value buffer points to valid memory.
A blog/woce-3/index.html

@@ -0,0 +1,213 @@

+<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=description content="Official Lonami's website"><meta name=viewport content="width=device-width, initial-scale=1.0, user-scalable=yes"><title> Writing our own Cheat Engine: Unknown initial value | Lonami's Blog </title><link rel=stylesheet href=/style.css><body><article><nav class=sections><ul class=left><li><a href=/>lonami's site</a><li><a href=/blog class=selected>blog</a><li><a href=/golb>golb</a></ul><div class=right><a href=https://github.com/LonamiWebs><img src=/img/github.svg alt=github></a><a href=/blog/atom.xml><img src=/img/rss.svg alt=rss></a></div></nav><main><h1 class=title>Writing our own Cheat Engine: Unknown initial value</h1><div class=time><p>2021-02-19</div><p>This is part 3 on the <em>Writing our own Cheat Engine</em> series:<ul><li><a href=/blog/woce-1>Part 1: Introduction</a> (start here if you're new to the series!)<li><a href=/blog/woce-2>Part 2: Exact Value scanning</a><li>Part 3: Unknown initial value</ul><p>In part 2 we left off with a bit of a cliff-hanger. Our little program is now able to scan for an exact value, remember the couple hundred addresses pointing to said value, and perform subsequent scans to narrow the list of addresses down until we're left with a handful of them.<p>However, it is not always the case that you have an exact value to work with. The best you can do in these cases is guess what the software might be storing. For example, it could be a floating point for your current movement speed in a game, or an integer for your current health.<p>The problem with this is that there are far too many possible locations storing our desired value. If you count misaligned locations, this means there is a different location to address every single byte in memory. A program with one megabyte of memory already has a <em>million</em> of addresses. Clearly, we need to do better than performing one million memory reads<sup class=footnote-reference><a href=#1>1</a></sup>.<p>This post will shift focus a bit from using <code>winapi</code> to possible techniques to perform the various scans.<h2 id=unknown-initial-value>Unknown initial value</h2><details open><summary>Cheat Engine Tutorial: Step 3</summary> <blockquote><p>Ok, seeing that you've figured out how to find a value using exact value let's move on to the next step.<p>First things first though. Since you are doing a new scan, you have to click on New Scan first, to start a new scan. (You may think this is straighforward, but you'd be surprised how many people get stuck on that step) I won't be explaining this step again, so keep this in mind Now that you've started a new scan, let's continue<p>In the previous test we knew the initial value so we could do a exact value, but now we have a status bar where we don't know the starting value. We only know that the value is between 0 and 500. And each time you click 'hit me' you lose some health. The amount you lose each time is shown above the status bar.<p>Again there are several different ways to find the value. (like doing a decreased value by... scan), but I'll only explain the easiest. "Unknown initial value", and decreased value. Because you don't know the value it is right now, a exact value wont do any good, so choose as scantype 'Unknown initial value', again, the value type is 4-bytes. (most windows apps use 4-bytes)click first scan and wait till it's done.<p>When it is done click 'hit me'. You'll lose some of your health. (the amount you lost shows for a few seconds and then disappears, but you don't need that) Now go to Cheat Engine, and choose 'Decreased Value' and click 'Next Scan' When that scan is done, click hit me again, and repeat the above till you only find a few.<p>We know the value is between 0 and 500, so pick the one that is most likely the address we need, and add it to the list. Now change the health to 5000, to proceed to the next step.</blockquote></details><h2 id=dense-memory-locations>Dense memory locations</h2><p>The key thing to notice here is that, when we read memory from another process, we do so over <em>entire regions</em>. A memory region is represented by a starting offset, a size, and a bunch of other things like protection level.<p>When running the first scan for an unknown value, all we need to remember is the starting offset and size for every single region. All the candidate locations that could point to our value fall within this range, so it is enough for us to store the range definition, and not every location within it.<p>To gain a better understanding of what this means, let's come up with a more specific scenario. With our current approach of doing things, we store an address (<code>usize</code>) for every location pointing to our desired value. In the case of unknown values, all locations are equally valid, since we don't know what value they should point to yet, and any value they point to is good. With this representation, we would end up with a very large vector:<pre><code class=language-rust data-lang=rust>let locations = vec![0x2000, 0x2001, ..., 0x20ff, 0x2100]; +</code></pre><p>This representation is dense. Every single number in the range <code>0x2000..=0x2100</code> is present. So why bother storing the values individually when the range is enough?:<pre><code class=language-rust data-lang=rust>let locations = EntireRegion { range: 0x2000..=0x2100 }; +</code></pre><p>Much better! With two <code>usize</code>, one for the starting location and another for the end, we can indicate that we care about all the locations falling in that range.<p>In fact, some accessible memory regions immediately follow eachother, so we could even compact this further and merge regions which are together. But due to their potential differences with regards to protection levels, we will not attempt to merge regions.<p>We don't want to get rid of the old way of storing locations, because once we start narrowing them down, we will want to go back to storing just a few candidates. To keep things tidy, let's introduce a new <code>enum</code> representing either possibility:<pre><code class=language-rust data-lang=rust>use std::ops::Range; + +pub enum CandidateLocations { + Discrete { + locations: Vec&LTusize>, + }, + Dense { + range: Range&LTusize>, + } +} +</code></pre><p>Let's also introduce another <code>enum</code> to perform the different scan types. For the time being, we will only worry about looking for <code>i32</code> in memory:<pre><code class=language-rust data-lang=rust>pub enum Scan { + Exact(i32), + Unknown, +} +</code></pre><h2 id=storing-scanned-values>Storing scanned values</h2><p>When scanning for exact values, it's not necessary to store the value found. We already know they're all the same, for example, value <code>42</code>. However, if the value is unknown, we do need to store it so that we can compare it in a subsequent scan to see if the value is the same or it changed. This means the value can be "any within" the read memory chunk:<pre><code class=language-rust data-lang=rust>pub enum Value { + Exact(i32), + AnyWithin(Vec&LTu8>), +} +</code></pre><p>For every region in memory, there will be some candidate locations and a value (or value range) we need to compare against in subsequent scans:<pre><code class=language-rust data-lang=rust>pub struct Region { + pub info: winapi::um::winnt::MEMORY_BASIC_INFORMATION, + pub locations: CandidateLocations, + pub value: Value, +} +</code></pre><p>With all the data structures needed setup, we can finally refactor our old scanning code into a new method capable of dealing with all these cases. For brevity, I will omit the exact scan, as it remains mostly unchanged:<pre><code class=language-rust data-lang=rust>use winapi::um::winnt::MEMORY_BASIC_INFORMATION; + +... + +// inside `impl Process` +pub fn scan_regions(&self, regions: &[MEMORY_BASIC_INFORMATION], scan: Scan) -> Vec&LTRegion> { + regions + .iter() + .flat_map(|region| match scan { + Scan::Exact(n) => todo!("old scan implementation"), + Scan::Unknown => { + let base = region.BaseAddress as usize; + match self.read_memory(region.BaseAddress as _, region.RegionSize) { + Ok(memory) => Some(Region { + info: region.clone(), + locations: CandidateLocations::Dense { + range: base..base + region.RegionSize, + }, + value: Value::AnyWithin(memory), + }), + Err(_) => None, + } + } + }) + .collect() +} +</code></pre><p>Time to try it out!<pre><code class=language-rust data-lang=rust>impl CandidateLocations { + pub fn len(&self) -> usize { + match self { + CandidateLocations::Discrete { locations } => locations.len(), + CandidateLocations::Dense { range } => range.len(), + } + } +} + +... + +fn main() { + // -snip- + + println!("Scanning {} memory regions", regions.len()); + let last_scan = process.scan_regions(&ampregions, Scan::Unknown); + println!( + "Found {} locations", + last_scan.iter().map(|r| r.locations.len()).sum::&LTusize>() + ); +} +</code></pre><pre><code>Scanning 88 memory regions +Found 3014656 locations +</code></pre><p>If we consider misaligned locations, there is a lot of potential addresses where we could look for. Running the same scan on Cheat Engine yields <code>2,449,408</code> addresses, which is pretty close. It's probably skipping some additional regions that we are considering. Emulating Cheat Engine to perfection is not a concern for us at the moment, so I'm not going to investigate what regions it actually uses.<h2 id=comparing-scanned-values>Comparing scanned values</h2><p>Now that we have performed the initial scan and have stored all the <code>CandidateLocations</code> and <code>Value</code>, we can re-implement the "next scan" step to handle any variant of our <code>Scan</code> enum. This enables us to mix-and-match any <code>Scan</code> mode in any order. For example, one could perform an exact scan, then one for decreased values, or start with unknown scan and scan for unchanged values.<p>The tutorial suggests using "decreased value" scan, so let's start with that:<pre><code class=language-rust data-lang=rust>pub enum Scan { + Exact(i32), + Unknown, + Decreased, // new! +} +</code></pre><p>Other scanning modes, such as decreased by a known amount rather than any decrease, increased, unchanged, changed and so on, are not very different from the "decreased" scan, so I won't bore you with the details.<p>I will use a different method to perform a "rescan", since the first one is a bit more special in that it doesn't start with any previous values:<pre><code class=language-rust data-lang=rust>pub fn rescan_regions(&self, regions: &[Region], scan: Scan) -> Vec&LTRegion> { + regions + .iter() + .flat_map(|region| match scan { + Scan::Decreased => { + let mut locations = Vec::new(); + match region.locations { + CandidateLocations::Dense { range } => { + match self.read_memory(range.start, range.end - range.start) { + Ok(memory) => match region.value { + Value::AnyWithin(previous) => { + memory + .windows(4) + .zip(previous.windows(4)) + .enumerate() + .step_by(4) + .for_each(|(offset, (new, old))| { + let new = i32::from_ne_bytes([ + new[0], new[1], new[2], new[3], + ]); + let old = i32::from_ne_bytes([ + old[0], old[1], old[2], old[3], + ]); + if new < old { + locations.push(range.start + offset); + } + }); + + Some(Region { + info: region.info.clone(), + locations: CandidateLocations::Discrete { locations }, + value: Value::AnyWithin(memory), + }) + } + _ => todo!(), + }, + _ => todo!(), + } + } + _ => todo!(), + } + } + _ => todo!(), + }) + .collect() +} +</code></pre><p>If you've skimmed over that, I do not blame you. Here's the summary: for every existing region, when executing the scan mode "decreased", if the previous locations were dense, read the entire memory region. On success, if the previous values were a chunk of memory, iterate over the current and old memory at the same time, and for every aligned <code>i32</code>, if the new value is less, store it.<p>It's also making me ill. Before I leave a mess on the floor, does it work?<pre><code class=language-rust data-lang=rust>std::thread::sleep(std::time::Duration::from_secs(10)); +let last_scan = process.rescan_regions(&last_scan, Scan::Decreased); +println!( + "Found {} locations", + last_scan.iter().map(|r| r.locations.len()).sum::&LTusize>() +); +</code></pre><pre><code class=language-rust data-lang=rust>Found 3014656 locations +Found 177 locations +</code></pre><p>Okay, great, let's clean up this mess…<h2 id=refactoring>Refactoring</h2><p>Does it also make you uncomfortable to be writing something that you know will end up <em>huge</em> unless you begin refactoring other parts right now? I definitely feel that way. But I think it's good discipline to push through with something that works first, even if it's nasty, before going on a tangent. Now that we have the basic implementation working, let's take on this monster before it eats us alive.<p>First things first, that method is inside an <code>impl</code> block. The deepest nesting level is 13. I almost have to turn around my chair to read the entire thing out!<p>Second, we're nesting four matches. Three of them we care about: scan, candidate location, and value. If each of these <code>enum</code> has <code>S</code>, <code>C</code> and <code>V</code> variants respectively, writing each of these by hand will require <code>S * C * V</code> different implementations! Cheat Engine offers 10 different scans, I can think of at least 3 different ways to store candidate locations, and another 3 ways to store the values found. That's <code>10 * 3 * 3 = 90</code> different combinations. I am not willing to write out all these<sup class=footnote-reference><a href=#2>2</a></sup>, so we need to start introducing some abstractions. Just imagine what a monster function you would end with! The horror!<p>Third, why is the scan being executed in the process? This is something that should be done in the <code>impl Scan</code> instead!<p>Let's begin the cleanup:<pre><code class=language-rust data-lang=rust>pub fn rescan_regions(&self, regions: &[Region], scan: Scan) -> Vec&LTRegion> { + todo!() +} +</code></pre><p>I already feel ten times better.<p>Now, this method will unconditionally read the entire memory region, even if the scan or the previous candidate locations don't need it<sup class=footnote-reference><a href=#3>3</a></sup>. In the worst case with a single discrete candidate location, we will be reading a very large chunk of memory when we could have read just the 4 bytes needed for the <code>i32</code>. On the bright side, if there <em>are</em> more locations in this memory region, we will get read of them at the same time<sup class=footnote-reference><a href=#4>4</a></sup>. So even if we're moving more memory around all the time, it isn't <em>too</em> bad.<pre><code class=language-rust data-lang=rust>regions + .iter() + .flat_map( + |region| match self.read_memory(region.info.BaseAddress as _, region.info.RegionSize) { + Ok(memory) => todo!(), + Err(err) => { + eprintln!( + "Failed to read {} bytes at {:?}: {}", + region.info.RegionSize, region.info.BaseAddress, err, + ); + None + } + }, + ) + .collect() +</code></pre><p>Great! If reading memory succeeds, we want to rerun the scan:<pre><code class=language-rust data-lang=rust>Ok(memory) => Some(scan.rerun(region, memory)), +</code></pre><p>The rerun will live inside <code>impl Scan</code>:<pre><code class=language-rust data-lang=rust>pub fn rerun(&self, region: &Region, memory: Vec&LTu8>) -> Region { + match self { + Scan::Exact(_) => self.run(region.info.clone(), memory), + Scan::Unknown => region.clone(), + Scan::Decreased => todo!(), + } +} +</code></pre><p>An exact scan doesn't care about any previous values, so it behaves like a first scan. The first scan is done by the <code>run</code> function (it contains the implementation factored out of the <code>Process::scan_regions</code> method), which only needs the region information and the current memory chunk we just read.<p>The unknown scan leaves the region unchanged: any value stored is still valid, because it is unknown what we're looking for.<p>The decreased scan will have to iterate over all the candidate locations, and compare them with the current memory chunk. But this time, we'll abstract this iteration too:<pre><code class=language-rust data-lang=rust>impl Region { + fn iter_locations<'a>( + &'a self, + new_memory: &'a [u8], + ) -> impl Iterator&LTItem = (usize, i32, i32)> + 'a { + match &self.locations { + CandidateLocations::Dense { range } => range.clone().step_by(4).map(move |addr| { + let old = self.value_at(addr); + let new = i32::from_ne_bytes([ + new_memory[0], + new_memory[1], + new_memory[2], + new_memory[3], + ]); + (addr, old, new) + }), + _ => todo!(), + } + } +} +</code></pre><p>For a dense candidate location, we iterate over all the 4-aligned addresses (fast scan for <code>i32</code> values), and yield <code>(current address, old value, new value)</code>. This way, the <code>Scan</code> can do anything it wants with the old and new values, and if it finds a match, it can use the address.<p>The <code>value_at</code> method will deal with all the <code>Value</code> variants:<pre><code class=language-rust data-lang=rust>fn value_at(&self, addr: usize) -> i32 { + match &self.value { + Value::AnyWithin(chunk) => { + let base = addr - self.info.BaseAddress as usize; + let bytes = &chunk[base..base + 4]; + i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) + } + _ => todo!(), + } +} +</code></pre><p>This way, <code>iter_locations</code> can easily use any value type. With this, we have all <code>enum</code> covered: <code>Scan</code> in <code>rerun</code>, <code>CandidateLocation</code> in <code>iter_locations</code>, and <code>Value</code> in <code>value_at</code>. Now we can add as many variants as we want, and we will only need to update a single <code>match</code> arm for each of them. Let's implement <code>Scan::Decreased</code> and try it out:<pre><code class=language-rust data-lang=rust>pub fn rerun(&self, region: &Region, memory: Vec&LTu8>) -> Region { + match self { + Scan::Decreased => Region { + info: region.info.clone(), + locations: CandidateLocations::Discrete { + locations: region + .iter_locations(&memory) + .flat_map(|(addr, old, new)| if new < old { Some(addr) } else { None }) + .collect(), + }, + value: Value::AnyWithin(memory), + },, + } +} +</code></pre><pre><code>Found 3014656 locations +Found 223791 locations +</code></pre><p>Hmm… before we went down from <code>3014656</code> to <code>177</code> locations, and now we went down to <code>223791</code>. Where did we go wrong?<p>After spending several hours on this, I can tell you where we went wrong. <code>iter_locations</code> is always accessing the memory range <code>0..4</code>, and not the right address. Here's the fix:<pre><code class=language-rust data-lang=rust>CandidateLocations::Dense { range } => range.clone().step_by(4).map(move |addr| { + let old = self.value_at(addr); + let base = addr - self.info.BaseAddress as usize; + let bytes = &new_memory[base..base + 4]; + let new = i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); + (addr, old, new) +}), +</code></pre><h2 id=going-beyond>Going beyond</h2><p>Let's take a look at other possible <code>Scan</code> types. Cheat Engine supports the following initial scan types:<ul><li>Exact Value<li>Bigger than…<li>Smaller than…<li>Value between…<li>Unknown initial value</ul><p>"Bigger than" and "Smaller than" can both be represented by "Value between", so it's pretty much just three.<p>For subsequent scans, in addition to the scan types described above, we find:<ul><li>Increased value<li>Increased value by…<li>Decreased value<li>Decreased value by…<li>Changed value<li>Unchanged value</ul><p>Not only does Cheat Engine provide all of these scans, but all of them can also be negated. For example, "find values that were not increased by 7". One could imagine to also support things like "increased value by range". For the increased and decreased scans, Cheat Engine also supports "at least xx%", so that if the value changed within the specified percentage interval, it will be considered.<p>What about <code>CandidateLocations</code>? I can't tell you how Cheat Engine stores these, but I can tell you that <code>CandidateLocations::Discrete</code> can still be quite inefficient. Imagine you've started with a scan for unknown values and then ran a scan for unchanged valueus. Most values in memory will have been unchanged, but with our current implementation, we are now storing an entire <code>usize</code> address for each of these. One option would be to introduce <code>CandidateLocations::Sparse</code>, which would be a middle ground. You could implement it like <code>Dense</code> and include a vector of booleans telling you which values to consider, or go smaller and use a bitstring or bit vector. You could use a sparse vector data structure.<p><code>Value</code> is very much like <code>CandidateLocations</code>, except that it stores a value to compare against and not an address. Here we can either have an exact value, or an older copy of the memory. Again, keeping a copy of the entire memory chunk when all we need is a handful of values is inefficient. You could keep a mapping from addresses to values if you don't have too many. Or you could shrink and fragment the copied memory in a more optimal way. There's a lot of room for improvement!<p>What if, despite all of the efforts above, we still don't have enough RAM to store all this information? The Cheat Engine Tutorial doesn't use a lot of memory, but as soon as you try scanning bigger programs, like games, you may find yourself needing several gigabytes worth of memory to remember all the found values in order to compare them in subsequent scans. You may even need to consider dumping all the regions to a file and read from it to run the comparisons. For example, running a scan for "unknown value" in Cheat Engine brings its memory up by the same amount of memory used by the process scanned (which makes sense), but as soon as I ran a scan for "unchanged value" over the misaligned values, Cheat Engine's disk usage skyrocketed to 1GB/s (!) for several seconds on my SSD. After it finished, memory usage went down to normal. It was very likely writing out all candidate locations to disk.<h2 id=finale>Finale</h2><p>There is a lot of things to learn from Cheat Engine just by observing its behaviour, and we're only scratching its surface.<p>In the next post, we'll tackle the fourth step of the tutorial: Floating points. So far, we have only been working with <code>i32</code> for simplicity. We will need to update our code to be able to account for different data types, which will make it easy to support other types like <code>i16</code>, <code>i64</code>, or even strings, represented as an arbitrary sequence of bytes.<p>As usual, you can <a href=https://github.com/lonami/memo>obtain the code for this post</a> over at my GitHub. You can run <code>git checkout step3</code> after cloning the repository to get the right version of the code. This version is a bit cleaner than the one presented in the blog, and contains some of the things described in the <a href=https://lonami.dev/blog/woce-3/#going-beyond>Going beyond</a> section. Until next time!<h3 id=footnotes>Footnotes</h3><div class=footnote-definition id=1><sup class=footnote-definition-label>1</sup><p>Well, technically, we will perform a million memory reads<sup class=footnote-reference><a href=#5>5</a></sup>. The issue here is the million calls to <code>ReadProcessMemory</code>, not reading memory per se.</div><div class=footnote-definition id=2><sup class=footnote-definition-label>2</sup><p>Not currently. After a basic implementation works, writing each implementation by hand and fine-tuning them by treating each of them as a special case could yield significant speed improvements. So although it would be a lot of work, this option shouldn't be ruled out completely.</div><div class=footnote-definition id=3><sup class=footnote-definition-label>3</sup><p>You could ask the candidate locations where one should read, which would still keep the code reasonably simple.</div><div class=footnote-definition id=4><sup class=footnote-definition-label>4</sup><p>You could also optimize for this case by determining both the smallest and largest address, and reading enough to cover them both. Or apply additional heuristics to only do so if the ratio of the size you're reading compared to the size you need isn't too large and abort the joint read otherwise. There is a lot of room for optimization here.</div><div class=footnote-definition id=5><sup class=footnote-definition-label>5</sup><p>(A footnote in a footnote?) The machine registers, memory cache and compiler will all help lower this cost, so the generated executable might not actually need that many reads from RAM. But that's getting way too deep into the details now.</div></main><footer><div><p>Share your thoughts, or simply come hang with me <a href=https://t.me/LonamiWebs><img src=/img/telegram.svg alt=Telegram></a> <a href=mailto:totufals@hotmail.com><img src=/img/mail.svg alt=Mail></a></div></footer></article><p class=abyss>Glaze into the abyss… Oh hi there!
M sitemap.xmlsitemap.xml

@@ -103,7 +103,7 @@ <lastmod>2019-06-03</lastmod>

</url> <url> <loc>https://lonami.dev/blog/posts/</loc> - <lastmod>2018-02-03</lastmod> + <lastmod>2021-02-19</lastmod> </url> <url> <loc>https://lonami.dev/blog/ribw/</loc>

@@ -194,11 +194,15 @@ <lastmod>2020-07-03</lastmod>

</url> <url> <loc>https://lonami.dev/blog/woce-1/</loc> - <lastmod>2021-02-16</lastmod> + <lastmod>2021-02-19</lastmod> </url> <url> <loc>https://lonami.dev/blog/woce-2/</loc> - <lastmod>2021-02-16</lastmod> + <lastmod>2021-02-19</lastmod> + </url> + <url> + <loc>https://lonami.dev/blog/woce-3/</loc> + <lastmod>2021-02-19</lastmod> </url> <url> <loc>https://lonami.dev/blog/world-edit/</loc>