This is the 4th challenge from FireEye's 2015 "FLARE On" challenge (http://flare-on.com/)
For a couple reasons this one took me a while to get going on... First, my VM didn't have the required mfc100u.dll:
Ok, I'll just grab a random dll off the internet and try that :)
Taking a closer look at the youPecks.exe file, it looks like it's UPX packed. Let's see what happens when we unpack it with the UPX utility's -d option and run the two versions:
Hmm, that's interesting.
While I didn't look into why exactly the manually unpacked version crashes instead of printing the "2 + 2 = 5" I saw from other people, knowing that the behavior is somehow changed, we're good enough to keep going...
Let's review what happens when we (a) execute a UPX-packed binary and (b) use UPX to unpack a packed binary.
In (a), a bit of unpacking code that's embedded within the .exe file is executed first. This performs the unpacking procedure, loads imports, and continues the execution of the original program.
In (b), the UPX utility is executed, which reads the UPX header of the packed binary and unpacks the EXE. The stub from (a) is not directly used and will be subsequently ignored.
This means that with the case of (a), additional code can be patched into the original packed binary that will cause the behavior of the EXE to be different between the packed & unpacked versions.
Let's look at the original youPecks.exe in IDA.
One spot that sticks out is at the end of the unpacking stub, it looks like a value in memory is being set to a hard-coded '4' value:
This seems to be right after an XOR loop that looks to be swapping the case of an alphabet string.
Setting a breakpoint confirms that that's the section of code critical to ensuring what's printed is "2 + 2 = 4" and the other function it performs is swapping the case in the string that will later be used for base64 decoding...
If we keep moving on and let the execution jump to the unpacked code, it looks more like a traditional program:
Looking at the unpacked code in IDA, we can see some nice structure if/else chains kicked off after it does something with GetCommandLineW, atoi, and the current hour from _localtime64_s:
It also seems to be checking something with or using specific base64-encoded strings in each block...
Looking closer, it looks like it creates a vector object using these strings and then decides which to use with the current hour & value passed in on the command line.
If we pick the base64 text coming from each of the first blocks, we should be able to try to manually decrypt the data:
from base64 import b64decode
data = b64decode("XTd3NiPLZBQ5N1FqkBN+a/Av6SpqBS/K".swapcase())
xor = b64decode("K7IfRF4nOiNn9Jsqt9wFCq==".swapcase())
for x in range(len(data)):
print(chr(xor[x % len(xor)] ^ data[x]))