CTF: Production Fleet Has A Wrong RPM

A fleet-wide package audit on your Amazon Linux hosts flagged one EC2 instance as drifted. Its foo RPM doesn't match the one published in the official AL repo. Same name, same version, same release; but the copy pulled off the instance is a little bigger than what the mirror ever shipped. Someone re-rolled the package before it landed on that box, and you, as the on-caller, need to find out what's going on.

You've been handed both RPMs straight off disk:

  • mirror/foo-1.2.3-1.x86_64.rpm : The package from the official Amazon Linux repo.
  • suspect/foo-1.2.3-1.x86_64.rpm: The copy pulled off the drifted EC2 instance.

Figure out what's going on with this weird situation, and recover the flag.

Flag Format: F{...}


Hint #1

Same NEVRA, different size. An RPM is more than the files it drops on disk, it's a container with a header, a payload, and install-time logic. Don't just diff the files (rpm -qlp); diff everything the package will do (rpm -qp --scripts).

Notice that there's an extra file in the suspected RPM!

Hint #2

The suspect package runs something at install time that the mirror package doesn't. Read that scriptlet carefully: it provisions a small file somewhere under /etc. Note both where it goes.

Hint #3

If you don't know what to do with the helper binary, perhaps try to see what does it "tell" you :). There's a nice command that gives this: strings. Whenever I see something really looking weird, perhaps a set of hex or a number, I always save it a side in my notes.

Hint #4

Helper seems to be build with function symbols. Instead of reading all of its assembly, perhaps check for the names it exposes. You colleuge ones mentioned about a tool called nm, perhaps it's just for this problem?

Hint #5

The nm command gives us a some understanding of the pipeline. There's transform_activation_key, read_salt, check_activation_key and encode_as_hex functions. I assume order is clear in your mind as well,

It looks like the weird hexadecimal in strings output will help us somehow here.

Hint #6

Since it's clear which function handles the transformation of the activation key, we can just deassemble it to see what's going on inside. The famous tool for it is objdump. Do not try to decode every instruction. Look for the instruction that combines one input byte with one salt byte. Its mnemonic tells you the operation being used. I mean asking for AI help is OK here :).

Hint #7

The XOR instruction in the disassembly gives the operation away, right? We have an input, a salt, and a suspicious hexadecimal target from strings. What relationship could connect them? To me, it looks like:

target = hex(input XOR repeating_salt)

Does that help you recover the input?

Hint #8

Luckily it is a XOR statement, so that we can easily use it's properties: (A XOR B) XOR B = A First get rid of the hexadecimal to make stuff easy. Afterwards, apply the repeating salt to the non-hex target you found.

Hint #9

Let me help you with a Python function to decode the activation key back.

target = bytes.fromhex("077d6a0c001f6e7c")
salt = b"AMZN"

activation_key = bytes(
byte ^ salt[index % len(salt)]
for index, byte in enumerate(target)
)

print(activation_key.decode("ascii"))