What does this XOR do?

I'm trying to understand exactly what is happening in the below loop. I've commented in what I believe is happening. I came to these conclusions by googling every op code and trying to understand what it means in addition to running the code in ImmunityDebugger and observing behavior.

I'm not sure if that is the most efficient means of research. Please let me know if there are other best practices for discovering functionality of relatively small selections of code.

What happens at memory address 00401053? What does XOR do in this case?

0040104B  |. 31C9           XOR ECX,ECX
0040104D  |> 8A81 58214000  /MOV AL,BYTE PTR DS:[ECX+402158] ;Move first byte of [ECX+402158] into AL
00401053  |. 34 7D          |XOR AL,7D                       ;Not sure what this means
00401055  |. 3A81 40214000  |CMP AL,BYTE PTR DS:[ECX+402140] ;Compare AL with the first byte of [ECX+402140]
0040105B     75 1E          |JNZ SHORT i_am_hap.0040107B     ;Jump out of loop if not zero << What does that mean?
0040105D  |. 41             |INC ECX                         ;increment ECX value
0040105E  |. 83F9 18        |CMP ECX,18                      ;loop runs 18 times
00401061    ^7C EA          \JL SHORT i_am_hap.0040104D      ;If above CMP fails restart the loop
• AL=AL^0x7d, ^ means xor – w s Jul 30 '15 at 6:34
• Please solve the Flare challenges yourself ;) – Carlos Garcia Jul 30 '15 at 13:51

Loop

First of all, when you say "loop runs 18 times", it is 0x18 times (hexa), actually, so 16+8=24 times.

Xor

XOR operand1, operand2

is nothing more than a logical XOR (11=> 0, 10=> 1, 01=> 1, 00=> 0).

Here it would be AL = AL XOR 01111101.

A 24 bytes string is likely stored at 0x402158 and is XORed with 0x7d. I say 24 bytes because this code loops 24 times, ECX being incremented each time, and the XORed byte is located at ECX+0x402158.

It means that every byte from 0x402158 to 0x402158 + 0x18 (0x402158 -> 0x402170) will be XORed with 0x7d.

JNZ

Jump out of loop if not zero << What does that mean?

The JNZ operand is following a comparison (CMP). Under the hood, CMP is no more than a subtraction. If subtraction result equals zero, then Zero Flag (ZF) is set to one. JNZ operand (Jump if Not Zero) only jumps if ZF is set to 0.

Conclusion

This being said, I thing you can figure out what is going on here. There is a string being XORed with 0x7d char after char. Every time a char is XORed, it's compared with another string located at 0x402140. If XORed char is different from the one in this string, then JNZ jumps. Pseudo C code would look like this :

Code edited thanks to Guntram Blohm comment

char chr;
int i;
char check[]="\x2a\x18\x11\x11\x5d\x19\x12\x13\x18\x5d\x30\x14\x0e\x09\x18\x0f\x5d\x3‌​5\x1c\x1e\x16\x13\x19\x12"
for (i=0; i<24; i++) {
argv[1][i] ^= '\x7d';
if (argv[1][i] != check[i]) {
break;
}
}
• Good answer, except that the check="something" somehow misses the point (and doesn't even have 24 characters). If someone runs the strings utility on this program, they'll see the "password" immediately. The point is using a check like char check[]="\x2a\x18\x11\x11\x5d\x19\x12\x13\x18\x5d\x30\x14\x0e\x09\x18\x0f\x5d\x35\x1c\x1e\x16\x13\x19\x12"; this hides the "password" but allows the program to check the input. – Guntram Blohm Jul 30 '15 at 7:42
• Good point, I wrote it a bit rashly. I edited my answer, thanks. – Hackndo Jul 30 '15 at 8:29

the snippet is functionally equivalent to this powershell script

copy paste to file.ps1 and run it like