Showing posts with label Daily Routine. Show all posts
Showing posts with label Daily Routine. Show all posts

Saturday, July 26, 2025

"INTs Aren't Integers and FLOATs aren't Real"

 

                            I was told this is a cat-submarine. Tail = Periscope. I believe it.
 


Over the past few weeks, I’ve been juggling two realities. On one side work: networks, and the daily exploration of security tasks in a banking environment. On the other, low-level code: free time, NASM, one instruction at a time.

 

I’ve been reviewing the basics—x86 syntax, memory layout, data definitions, etc etc etc. I'm following a series of videos, from a YouTuber that I appreciate, and although I found some information lacking or imprecise—particularly in the episode devoted to divisionit's still a good set of videos and I'd advise anyone to watch them here. Lately I've taken a gander at integers. How they’re stored, manipulated, compared, and what all those flags mean when you're moving bits around and trying to make sense of a program in GDB.

If you’ve spent more than a few hours in GDB (as I have, unreasonably so at times), you’ve probably done a CMP eax, ebx and then wondered what exactly happened to the flags. What’s the deal with CF, ZF, SF, and the rest of the alphabet soup? Why do certain jump instructions follow CMP, and not others?

So, quick refresher for the two family members that like me and still read this blog:

CMP just subtracts the second operand from the first, sets flags, and discards the result. The flags tell you the outcome, and then you pick the jump based on what you want to test.

InstructionMeaningFlags checked
JE / JZEqual (zero result)ZF = 1
JNE / JNZNot equalZF = 0
JL / JNGELess than (signed)SF != OF
JLE / JNGLess or equal (signed)ZF = 1 or SF != OF
JB / JCBelow (unsigned)CF = 1
JAAbove (unsigned)CF = 0 && ZF = 0

Notice those signed vs unsigned differences? JB isn’t "jump if smaller", it’s "jump if below"—unsigned. If you’re comparing signed ints, you should be using JL, JG, and so on.

Floats make it even more nuanced. UCOMISS xmm0, xmm1 for example, is how you compare scalar floats. That instruction sets flags similar to CMP, but works with IEEE 754 single-precision values, not integers. And yes, it’s aware of signs, NaNs, Infs, and the rest (of floating point hell).

Anyway, all that to say: this is kinda subtle, or at least it requires some study and care. IMO, totally worth learning. Most would disagree profoundly. I’ve been pushing myself to remember it, slowly but deliberately. You can check out some of the tiny experiments here. It’s not a project, more like a scratchpad that runs on opcodes and (lovely, quality) coffee.

 

                                                                 ...When in doubt, explain it to me. I'm anathema too.


 And you know what's fun? Mathematics! No, really.
I've seen it again and again: people treating floats as if they are basically the real numbers
(ℝ). They aren't!

Just take a look under the hood and you'll understand why.

"But OPQAM, I use Python/Java/Whatever. I don’t care about Assembly or floating-point registers!"

And that’s fair—until you try 0.1 + 0.2 and get 0.30000000000000004, or even 0.30000001192092895508. Then it might matter.

Can you think of a situation where such a small discrepancy could be a problem? I sure can. I can think of several, and some of them imply falling bridges.

Here’s the core issue: ints aren’t integers, and floats aren’t rationals.

 

An example

The decimal 0.1 becomes the binary: 0.0001100110011001100110011001100110011..., repeating infinitely.
But computers can’t store infinity. They cut off after some number of bits: ~23 bits for floats, ~52 bits for doubles. It’s like trying to store 1/3 in decimal — you can’t write 0.3333... forever. You round. You approximate. So do computers.

So, this means that you cannot represent 0.1 precisely.

 

The problem isn’t the mathematics — it’s representation.

How do systems and programmers deal with this?

  • Use decimal representations (decimal.Decimal) when exactness matters (e.g. money).

  • Use rational types that store fractions exactly (Fraction(1, 10)).

  • Use symbolic math when precision must be preserved throughout (SymPy, CAS software).

  • Or use fixed-point arithmetic — store cents instead of euros.

These are workarounds. The real solution? Know that floats are approximations, not truth.



                                                Accurate depiction of my two family members' faces as they read through this.


Meanwhile, back in the Real World, there was a CTF going on in the team. A colleague of mine created it and invited us all to some friendly competition for the next few weeks. Honestly? I will probably only do a couple CTFs before I turn my attention elsewhere. Having a family + hobbies + a day job does limit one's time. Still, I got to dip, and I managed to solve a challenge involving a simple—but satisfying—privilege escalation. I'm not going to give a lot of details, since it goes against the point of the 'contest' and it's actually requested by the site that we don't do it. But here's the 'trick': Classic PATH hijack. I dropped a fake ls binary into a writable dir (/tmp), positioned it early in $PATH, and executed the vulnerable binary which, instead of ls executed cat. Bang. Root shell. Dump flag. Walk away smiling.
This was, of course, allowed by purposefully using SETUID in the binary. A no-no. But there you have it. It was fun.

And yeah, sure—it’s not the most sophisticated vector ever, but the fact is, simple stuff works. You don't have to be fancy-schmancy to make something give you a 'win'. It is thus in Jiu Jitsu, and in illusionism. And so it is in hacking.

Also worth noting: a few days ago I got into a discussion with a colleague about TPM (Trusted Platform Module). I’ve blogged about the TPM issue here, but here’s the gist of it: I had to disable TPM on an old laptop (a very respectable ThinkPad x260) just to make the thing actually power off correctly. I tried everything—kernel parameters, ACPI tweaks, prayer (not really, but I totally could have!)—but nothing worked. Full shutdown always left the machine 'hot'.

Disabling TPM did the trick.

Why? Long story short: the TPM implementation on that hardware was tailored for Windows, and Linux support is... charitable at best. As for the discussion. That colleague warned me that in certain scenarios, like full power drains, I could end up with an unbootable machine if I lost TPM state. So I did what any sane people would do: I tested it again and again, simulating different scenarios.

 

Unplugged, drained, every scenario short of desoldering the CMOS battery. Result? Nothing broke. LUKS doesn’t need TPM. At least, not for the way I have this set up. In Linux, with this setting, TPM is optional unless you're deliberately tying encryption keys to it—and even then, tread carefully.

These tests were fun. They reminded me of the joy of breaking things on purpose, and the calm that comes with understanding exactly why something behaves the way it does.

So yeah, life’s been busy. I haven’t had much time to write (sentence never written by any amateur blogger ever). But I’m still here, still learning, and still hacking away.

Next up? I'll probably hit you up with some more ASM stuff as I keep on watching those videos and experimenting with stuff. Maybe some CTFs... who knows? Not me! And I'm right here. 

We’ll see.


Tuesday, December 31, 2024

Wherein We Face A Lindwyrm: don't do LeetCode

 

                    The Lyndwurm. Let's face it sooner. Not later.


Before diving into LeetCode, let me tell you this post was initially going to be about my journey completing a series of 30 Assembly CTFs on pwn.college. It still is, in a way, and I highly recommend that site to anyone interested in hacking and low-level programming (check that site─totally worth it). 

But somewhere along the way, I decided to shift the focus. So, bear with me while we explore LeetCode.

Let’s start with the disclaimers:

  • I’m happily employed.
  • My knowledge of the hiring process is limited to my own experiences and what I’ve observed.
  • Take everything I say here with a grain of salt.

What Are LeetCode Problems?

LeetCode-style problems are algorithmic and data structure challenges, often used in technical interviews to (supposedly) assess problem-solving skills, logic, and coding efficiency.

I’ve tried LeetCode. I even did a fair bit of it back in university while studying Python. And I’m here to tell you: it’s not for me. It's probably not for you, either.


Here are 10 reasons why I’ve left LeetCode by the wayside:


1. I’m not a programmer, nor do I want to be one.

I work in IT and am aiming to become a Cybersecurity professional, specifically a Reverse Engineer/Malware Analyst. In this realm, LeetCode is of very limited relevance, if any. My focus is on low-level code, systems, and security—not cranking out optimal algorithms for abstract, byte-sized, problems.


2. Time is sacred, and LeetCode doesn’t fit my priorities.

Mastering LeetCode takes time—lots of it. As someone who obsesses over how I spend my time, I refuse to pour hours into a skill I find doubtful in utility for my goals. Instead, I could be:

  • Diving deeper into malware analysis.
  • Learning more about CPU internals.
  • Experimenting with Reverse Engineering tools.
  • Or even doing other wholesome hobbies like: fishing, watching paint dry, or fine-tuning push-ups.

3. It consumes mental bandwidth I’d rather use elsewhere.

Focusing on LeetCode takes up space in my brain that I could dedicate to something more relevant or enjoyable. Cybersecurity is vast, and every moment I spend on coding puzzles is a moment I’m not spending on fun puzzles.


4. There are other ways to demonstrate my skills.

I maintain a public GitHub with projects I’ve built. If someone needs proof of my abilities, I can show my work or create something on demand. Writing scripts or automation tools in a real-world context is more relevant to my career than solving arbitrary LeetCode.


5. Secure, readable code > Clever one-liners.

LeetCode often rewards speed and brevity, which can lead to unreadable, messy solutions. Writing secure, stable, maintainable code that other humans can understand is far more valuable in real-world applications.


6. In cybersecurity, CTFs are the way to go.

Capture The Flag challenges (CTFs) are like games. They’re fun, align with the hacker spirit, and teach you practical skills. I’d rather do CTFs all day than grind through LeetCode puzzles.


7. Better ways to assess pressure and skills exist.

In addition to several other assessments, my current company included a 1.5-hour test during the hiring process that challenged me to work under pressure, adapt to new situations, conduct research, and document my process. It was hard, fun, and incredibly insightful. If they had instead asked me to solve 10 LeetCode problems, they wouldn’t have learned anything about my actual skills. No joke—this test was fantastic.


8. I’m not here to compete with kids who have all the time in the world.

If I have two free hours, I’ll use them to play in my malware lab—not grind Python or C snippets on Codewars. I have nothing to prove to anyone, and I’m not interested in chasing someone else’s benchmarks.

Years ago, I participated in a BJJ tournament and won (blue belt +40 years category). At the end of the tournament, all the blue belt winners were allowed to face each other in a 'free-for-all styled' match. I said no. I had nothing to prove. I knew the outcome, too─there was no point in fighting guys who had trained as long as I had but were 20 years younger and weighed 20 kilos more. 

Here's what I looked like after winning in my category:

                                                        Cute, huh? Third place didn't even get a medal. He got a broken rib and a trip to the hospital.


9. I’m not missing meaningful opportunities.

Sure, some companies prioritize LeetCode skills, but those are likely not the places I want to work at. I’d rather focus on preparing for roles that value my expertise in cybersecurity and low-level systems.

On the flip side, if I do receive a job offer from a company looking to assess my "cyber skills," I’ll be in a much stronger position if I’ve invested my time in honing those skills, rather than spending it on LeetCode.


10. Burnout is real.

Burnout is pervasive in IT. I’ve seen people so drained by their work that all they want is to clock out and forget anything technical. They crave time for hobbies, family, and friends, leaving the techie stuff for when it’s absolutely necessary. Not me. I dive into reverse engineering because I genuinely enjoy it, but I make sure to balance it with other hobbies, family time, and necessary downtime. Chasing someone else’s dream isn’t worth sacrificing my mental health.




Final Thoughts

For those who insist we must suffer through things we hate to secure a “dream job,” I leave you with this quote from Game of Thrones:



"INTs Aren't Integers and FLOATs aren't Real"

                                     I was told this is a cat-submarine. Tail = Periscope. I believe it.   Over the past few weeks, I’ve be...