# include <stdio.h>
# include <values.h>
int main (int argc, char** argv)
{
signed int i;
for (i=MININT; i<MAXINT; i++)
{
register arg=i;
register arg1=arg;
arg=arg>>0x1f;
arg=~arg;
arg=arg&arg1;
arg-=0x6fe5d5;
arg=arg^0x2eb22189;
arg=arg*0x1534162;
arg=arg^0x69f6bc7;
if (arg==230392619) {printf("%i\n",i);}
}
}
This one is exactly the same as the source because it generates to same assembler code (the type "register" is important!)
I thought of coding it in some scripting language, but was not sure how to code the arithmetic with 32 bit signed integers.
The result: a rocket fast program (takes a few seconds to complete) and some C back into my brain
Anybody did it in a scripting language? How?
I used Python, explicitly rounding modulo 2**32 in places. Rather than brute-forcing, having rewritten the steps, I worked back from the answer deciding which inputs at each step gave the right intermediate result. It wasn't too hard, though there were often several possible intermediates; however it always turned out that one was impossible due to an earlier step.
Probably much quicker to brute force it, though, as you say.
@gfoot yes indeed, running the assembler part in Delphi on an old P4 you only need 11 secs -- so it is not really efficient to recalculate backwards (although that looks quite easy too, but surely will take more than 11 s). This challenge was a kind of recreation - after a lot of really hard challenges ...
public class Blackbox {
public static void main(String[] args) {
int x = 0;
int s = 230392619;
int i = 0;
int ul = Integer.MAX_VALUE;
while (x!=s) {
x = ((( ul & i - 7333333 ) ^ 783425929 ) * 22233442 ) ^ 111111111;
i++;
}
System.out.println("Solution:"+(i-1));
}
}
I found the first few thousand values and worked out that the bit in position n is periodic in 2^n, so after working out what the last 16 bits had to be, I ended up with having to be congruent to 20148 mod 32768. That was enough to brute force in 15 mins.
i used brute force ... i had a machine lying around with a fast CPU and enough RAM to fit the entire system in. i used a tinycore linux and a ramdisk, to reduce IO. the shell script i used:
kne1p wrote:
I guess not, therefore the reverse calculation is only about twice as fast as the normal brute force approach.
Well, what you have to solve is the linear congruence equation: x*22233442 == 186968300 (mod 4294967296).
This can be done with knowledge of elementary number theory (extended euclidean algorithm). The time complexity is just O(logN) instead of O(N) where N is the largest number above.
megabreit wrote:(the type "register" is important!)
Actually, it works just fine without.
This was a great challenge!
At first, I tried to get the GLIBC version 2.0, since seemingly that was used for creating the binary. I found that version on the GNU ftp server. However it would not compile - there was always some error with some time header file(s) that I was not able to fix.
So I got myself a disassembler (I used IDA Pro Free), looked at the instructions, and decided to reverse engineer the code. This worked out quite nicely. My solution:
kne1p wrote:
I guess not, therefore the reverse calculation is only about twice as fast as the normal brute force approach.
Well, what you have to solve is the linear congruence equation: x*22233442 == 186968300 (mod 4294967296).
This can be done with knowledge of elementary number theory (extended euclidean algorithm). The time complexity is just O(logN) instead of O(N) where N is the largest number above.
+1
the extended euclidean algorithm got the division for me as well. it is actually the same problem as in the previous challenge Patience with the only difference being decompiling java class or elf binary.
This doesn't involve coding at all ! We could just calculate the answer by hand quite easily :p
I used gdb to disassemble the elf and used the value from the assembler code.
After finding boomerang could decompile it ... I wrote bruteforce to inverse the multiplication. It was that fast that I have not figured the euclidian algorithm will help.