IOLI 0x05

check again, it uses scanf() to get our input and pass it to check() as parameter.

  1. [0x080483d0]> pdd@main
  2. /* r2dec pseudo code output */
  3. /* ./crackme0x05 @ 0x8048540 */
  4. #include <stdint.h>
  5. int32_t main (void) {
  6. int32_t var_78h;
  7. int32_t var_4h;
  8. eax = 0;
  9. eax += 0xf;
  10. eax += 0xf;
  11. eax >>= 4;
  12. eax <<= 4;
  13. printf ("IOLI Crackme Level 0x05\n");
  14. printf ("Password: ");
  15. eax = &var_78h;
  16. scanf (0x80486b2, eax); // 0x80486b2 is %s
  17. eax = &var_78h;
  18. check (eax);
  19. eax = 0;
  20. return eax;
  21. }

the check() function:

  1. /* r2dec pseudo code output */
  2. /* ./crackme0x05 @ 0x80484c8 */
  3. #include <stdint.h>
  4. int32_t check (char * s) {
  5. char * var_dh;
  6. uint32_t var_ch;
  7. uint32_t var_8h;
  8. int32_t var_4h;
  9. char * format;
  10. int32_t var_sp_8h;
  11. var_8h = 0;
  12. var_ch = 0;
  13. do {
  14. eax = s;
  15. eax = strlen (eax);
  16. if (var_ch >= eax) {
  17. goto label_0;
  18. }
  19. eax = var_ch;
  20. eax += s;
  21. eax = *(eax);
  22. var_dh = al;
  23. eax = &var_4h;
  24. eax = &var_dh;
  25. sscanf (eax, eax, 0x8048668); // 0x8048668 is %d
  26. edx = var_4h;
  27. eax = &var_8h;
  28. *(eax) += edx;
  29. if (var_8h == 0x10) {
  30. eax = s;
  31. parell (eax);
  32. }
  33. eax = &var_ch;
  34. *(eax)++;
  35. } while (1);
  36. label_0:
  37. printf ("Password Incorrect!\n");
  38. return eax;
  39. }

The same, we can write our own C-like pseudo code.

  1. #include <stdint.h>
  2. int32_t check(char *s)
  3. {
  4. var_ch = 0;
  5. var_8h = 0;
  6. for (var_ch = 0; var_ch < strlen(s); ++var_ch)
  7. {
  8. var_dh = s[var_ch];
  9. sscanf(&var_dh, %d, &var_4h); // read from string[var_ch], store to var_4h
  10. var_8h += var_4h;
  11. if(var_8h == 0x10)
  12. parell(s);
  13. }
  14. printf("Password Incorrect!\n");
  15. return 0;
  16. }

The if condition becomes var_8h == 0x10. In addition, a new function call - parell(s) replace the printf("password OK")now. The next step is to reverse sym.parell.

  1. [0x08048484]> s sym.parell
  2. [0x08048484]> pdd@sym.parell
  3. /* r2dec pseudo code output */
  4. /* ./crackme0x05 @ 0x8048484 */
  5. #include <stdint.h>
  6. uint32_t parell (char * s) {
  7. int32_t var_4h;
  8. char * format;
  9. int32_t var_8h;
  10. eax = &var_4h;
  11. eax = s;
  12. sscanf (eax, eax, 0x8048668);
  13. eax = var_4h;
  14. eax &= 1;
  15. if (eax == 0) {
  16. printf ("Password OK!\n");
  17. exit (0);
  18. }
  19. return eax;
  20. }

the decompiled code looks well except the sscanf() function. It can be easily corrected by checking the assembly code.

  1. / 68: sym.parell (int32_t arg_8h);
  2. | ; var int32_t var_4h @ ebp-0x4
  3. | ; arg int32_t arg_8h @ ebp+0x8
  4. | ; var int32_t var_sp_4h @ esp+0x4
  5. | ; var int32_t var_8h @ esp+0x8
  6. | 0x08048484 55 push ebp
  7. | 0x08048485 89e5 mov ebp, esp
  8. | 0x08048487 83ec18 sub esp, 0x18
  9. | 0x0804848a 8d45fc lea eax, [var_4h]
  10. | 0x0804848d 89442408 mov dword [var_8h], eax
  11. | 0x08048491 c74424046886. mov dword [var_sp_4h], 0x8048668 ; [0x8048668:4]=0x50006425 %d
  12. | 0x08048499 8b4508 mov eax, dword [arg_8h]
  13. | 0x0804849c 890424 mov dword [esp], eax
  14. | 0x0804849f e800ffffff call sym.imp.sscanf ; int sscanf(const char *s, const char *format, ...)
  15. ....

The mov dword [esp], eax is the nearest instruction to sscanf (and it’s equivalent to a push instruction). It stores the string ‘s’ to the stack top (arg1). mov dword [var_sp_4h], 0x8048668 push ‘%d’ as arg2 into stack. var_8h (esp + 0x8) which keeps the address of var_4h is the arg3.

Finally we have the corrected pseudo code:

  1. uint32_t parell (char * s) {
  2. sscanf (s, %d, &var_4h);
  3. if ((var_4h & 1) == 0) {
  4. printf ("Password OK!\n");
  5. exit(0);
  6. }
  7. return 0;
  8. }

Now there are 2 constraints:

  • Digit Sum is 16 (0x10)
  • Must be an odd number (1 & number == 0)

The password is at our fingertips now.

  1. ./crackme0x05
  2. IOLI Crackme Level 0x05
  3. Password: 88
  4. Password OK!
  5. ./crackme0x05
  6. IOLI Crackme Level 0x05
  7. Password: 12346
  8. Password OK!

we can also use angr to solve it since we have two constraints to the password.