#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

uint32_t ror(uint32_t x, int n) {
    uint32_t bottom = x >> n;
    uint32_t top = x << (32 - n);
    return top | bottom;
}

uint32_t rol(uint32_t x, int n) {
    uint32_t top = x << n;
    uint32_t bottom = x >> (32 - n);
    return top | bottom;
}


int main(int argc, char *argv[]) {

    unsigned char program[] = "\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\xa1\x91\x04\x08\xba\x26\x00\x00\x00\xcd\x80\xb8\x03\x00\x00\x00\x31\xdb\xb9\x88\x91\x04\x08\xba\x33\x00\x00\x00\xcd\x80\x31\xc9\xb8\x80\x80\x04\x08\xbb\x23\x81\x04\x08\xe8\x5b\x00\x00\x00\x89\xca\xb9\x19\x00\x00\x00\xb8\x55\x91\x04\x08\xbb\x88\x91\x04\x08\xd1\xca\x8a\x44\x08\xff\x8a\x5c\x0b\xff\x30\xd8\x30\xd0\x75\x1b\x49\x75\xe3\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x24\x91\x04\x08\xba\x26\x00\x00\x00\xcd\x80\xeb\x16\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x4a\x91\x04\x08\xba\x0b\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\x31\xdb\xcd\x80\x29\xc3\x31\xc9\x02\x08\xc1\xc1\x03\x40\x4b\x75\xf7\xc3";

    unsigned char left[] = "\x1e\xcd\x2a\xd5\x34\x87\xfc\x78\x64\x35\x9d\xec\xde\x15\xac\x97\x99\xaf\x96\xda\x79\x26\x4f\x32\xe0";
    unsigned char right[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";

    uint32_t ecx = 0;
    uint32_t edx = 0;

    for (int i = 0; i < sizeof(program)-1; i++) {
        uint8_t cl = (ecx & 0xff);
        cl = cl + program[i];
        ecx = (ecx & 0xffffff00) | cl;
        ecx = rol(ecx, 3);
    }
    edx = ecx;
    ecx = 0x19;

    char *out = malloc(0x20);
    out[0x19] = 0;
    do {
        edx = ror(edx, 1);
        uint8_t dl = edx & 0xff;

        uint8_t al = left[ecx - 1];
        uint8_t bl = right[ecx - 1];
        uint8_t expected = ((al ^ bl) ^ dl);

        // we want al ^ bl == dl, so we need bl = al ^ dl as the current password char.
        out[ecx - 1] = al ^ dl;

        al = al ^ bl;
        al = al ^ dl;
        
    } while (--ecx != 0);

    printf("%s\n", out);

    return 0;
}
