integrato ;)
EffeTech HTTP sniffer reverse engineering 2°parte
Analisi di algoritmi, keygenning e cracking

Entrando all'interno della call CheckSerial troviamo il vero e proprio algoritmo di controllo del seriale, si tratta di un codice molto lungo e dispersivo, corredato di tanti controlli inutili che possono mandare fuori strada, iniziamo a vedere nei punti chiave cosa accade:
  1. 0040EAF0 <>PUSH -1
  2. 0040EAF2 PUSH EHSniffe.00457B38 ; SE handler installation
  3. 0040EAF7 MOV EAX,DWORD PTR FS:[0]
  4. 0040EAFD PUSH EAX
  5. 0040EAFE MOV DWORD PTR FS:[0],ESP
  6. 0040EB05 SUB ESP,2C
  7. 0040EB08 MOV EAX,DWORD PTR SS:[ESP+3C]
  8. 0040EB0C PUSH ESI
  9. 0040EB0D MOV ESI,DWORD PTR DS:[EAX] ; ESI = serial
  10. 0040EB0F MOV ECX,DWORD PTR DS:[ESI-C] ; ECX = strlen(serial)
  11. 0040EB12 CMP ECX,0F ; if (strlen(serial) > 0x0F)
  12. 0040EB15 MOV DWORD PTR SS:[ESP+14],...>
  13. 0040EB1D MOV DWORD PTR SS:[ESP+18],...>
  14. 0040EB25 MOV DWORD PTR SS:[ESP+1C],...>
  15. 0040EB2D MOV DWORD PTR SS:[ESP+20],...>
  16. 0040EB35 MOV DWORD PTR SS:[ESP+24],...>
  17. 0040EB3D MOV DWORD PTR SS:[ESP+28],...>
  18. 0040EB45 MOV DWORD PTR SS:[ESP+2C],...>
  19. 0040EB4D JGE SHORT EHSniffe._JUMP_09 ; Se si salto
  20. 0040EB4F XOR EAX,EAX
  21. 0040EB51 POP ESI
  22. 0040EB52 MOV ECX,DWORD PTR SS:[ESP+2C]
  23. 0040EB56 MOV DWORD PTR FS:[0],ECX
  24. 0040EB5D ADD ESP,38
  25. 0040EB60 RETN 4
Tutta questa prima parte di codice è inutile. Vengono impostati ESI e ECX e poi viene effettuato un controllo che sarà sempre vero. strlen(serial) è sempre > 0x0F (se non fosse uguale a 0x12 il programma sarebbe già terminato), proseguiamo:
  1. _JUMP_09 TEST ECX,ECX ; if (strlen(serial) >= strlen(serial))
  2. 0040EB65 PUSH EBP
  3. 0040EB66 MOV EBP,171E ; ! IMPORTANTE ! EBP = 0x171E
  4. 0040EB6B JGE SHORT EHSniffe._JUMP_10 ; Sempre verificato
  5. 0040EB6D PUSH 80070057
  6. 0040EB72 CALL EHSniffe.004010D0
  7. _JUMP_10 CMP ECX,1 ; if (strlen(serial) >= 1)
  8. 0040EB7A JGE SHORT EHSniffe._JUMP_11 ; Sempre verificato
  9. 0040EB7C PUSH 80070057
  10. 0040EB81 CALL EHSniffe.004010D0
  11. _JUMP_11 CMP ECX,2 ; if (strlen(serial) >= 2)
  12. 0040EB89 JGE SHORT EHSniffe._JUMP_12 ; Sempre verificato
  13. 0040EB8B PUSH 80070057
  14. 0040EB90 CALL EHSniffe.004010D0
  15. _JUMP_12 CMP ECX,3 ; if (strlen(serial) >= 3)
  16. 0040EB98 MOV DL,BYTE PTR DS:[ESI+2] ; DL = serial[2]
  17. 0040EB9B MOV BYTE PTR SS:[ESP+44],DL ; Salvo nello stack serial[2]
  18. 0040EB9F JGE SHORT EHSniffe._JUMP_13 ; Sempre verificato
  19. 0040EBA1 PUSH 80070057
  20. 0040EBA6 CALL EHSniffe.004010D0
  21. _JUMP_13 CMP ECX,4 ; if (strlen(serial) >= 4)
  22. 0040EBAE PUSH EBX ; Salvo nello stack 0x171E
  23. 0040EBAF MOV BL,BYTE PTR DS:[ESI+3] ; BL = serial[3]
  24. 0040EBB2 JGE SHORT EHSniffe._JUMP_14 ; Sempre verificato
  25. 0040EBB4 PUSH 80070057
  26. 0040EBB9 CALL EHSniffe.004010D0
  27. _JUMP_14 MOV DL,BYTE PTR DS:[ESI+4] ; DL = serial[4]
  28. 0040EBC1 PUSH EDI
Anche qui ci sono parecchi controlli sempre verificati, quindi un sacco di istruzioni che non verranno mai eseguite. Comunque il programma si salva nei registri e nello stack particolari determinati caratteri del seriale e un numero molto importante che ci tornerà utile dopo, 0x171E. Andiamo avanti con l'analisi:
  1. 0040EBC2 MOVSX EAX,BL ; EAX = serial[3]
  2. 0040EBC5 MOV EDI,64 ; EDI = 0x64
  3. 0040EBCA SUB EDI,EAX ; EDI = 0x64 - serial[3]
  4. 0040EBCC MOVSX EAX,BYTE PTR SS:[ESP+4C] ; EAX = serial[2]
  5. 0040EBD1 LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; EAX *= 3
  6. 0040EBD4 MOVSX EDX,DL ; EDX = serial[4]
  7. 0040EBD7 LEA EAX,DWORD PTR DS:[EAX+EDI*2] ; EAX += EDI * 2
  8. 0040EBDA ADD EAX,EDX ; EAX += serial[4]
  9. 0040EBDC MOVSX EDX,BYTE PTR DS:[ESI+1] ; EDX = serial[1]
  10. 0040EBE0 ADD EAX,EDX ; EAX += serial[1]
  11. 0040EBE2 MOVSX EDX,BYTE PTR DS:[ESI] ; EDX = serial[0]
  12. 0040EBE5 LEA EAX,DWORD PTR DS:[EDX+EAX*2] ; EAX = serial[0] + EAX * 2
  13. 0040EBE8 CDQ ; DWORD EAX -> QWORD EDX:EAX
  14. 0040EBE9 MOV EDI,0E8 ; EDI = 0xE8
  15. 0040EBEE IDIV EDI ; EAX = EAX / 0xE8 (EDX = resto)
  16. 0040EBF0 CMP ECX,3 ; if (strlen(serial) >= 3)
  17. 0040EBF3 MOV BYTE PTR SS:[ESP+18],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Ora si parte con il l'algoritmo che ci interessa. Il codice d'ora in poi sarà sempre circa uguale, verranno svolte alcune operazioni su determinati caratteri del seriale e alla fine verrà salvato sullo stack il resto di una divisione. Questa operazine verrà svolta (in modo diverso ma simile) 8 volte, il codice ad alto livello che compie questa prima operazione può essere riassunto in:
  1. resto[0] = ((((serial[2] * 3) + ((0x64 - serial[3]) * 2 ))
  2. + serial[4] + serial[1]) * 2 + serial[0]) % 0xE8;
Come detto d'ora in poi l'algoritmo fa sempre praticamente la stessa cosa, cambiando operazioni e lettere, mi limitero quindi a riportare l'assembly opportunamente commentato e il corrispettivo algoritmo ad alto livello
  1. 0040EBF7 JGE SHORT EHSniffe._JUMP_15 ; Sempre verificato
  2. 0040EBF9 PUSH 80070057
  3. 0040EBFE CALL EHSniffe.004010D0
  4. _JUMP_15 CMP ECX,4 ; if (strlen(serial) >= 4)
  5. 0040EC06 JGE SHORT EHSniffe._JUMP_16 ; Sempre verificato
  6. 0040EC08 PUSH 80070057
  7. 0040EC0D CALL EHSniffe.004010D0
  8. _JUMP_16 CMP ECX,0E ; if (strlen(serial) >= 0x0E)
  9. 0040EC15 JGE SHORT EHSniffe._JUMP_17 ; Sempre verificato
  10. 0040EC17 PUSH 80070057
  11. 0040EC1C CALL EHSniffe.004010D0
  12. _JUMP_17 CMP ECX,6 ; if (strlen(serial) >= 6)
  13. 0040EC24 JGE SHORT EHSniffe._JUMP_18 ; Sempre verificato
  14. 0040EC26 PUSH 80070057
  15. 0040EC2B CALL EHSniffe.004010D0
  16. _JUMP_18 MOVSX EAX,BYTE PTR DS:[ESI+6] ; EAX = serial[6]
  17. 0040EC34 MOVSX EDX,BYTE PTR DS:[ESI+E] ; EDX = serial[14]
  18. 0040EC38 LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; EAX *= 3
  19. 0040EC3B LEA EAX,DWORD PTR DS:[EAX+EDX*2] ; EAX += EDX * 2
  20. 0040EC3E MOVSX EDX,BYTE PTR DS:[ESI+4] ; EDX = serial[4]
  21. 0040EC42 ADD EAX,EDX ; EAX += serial[4]
  22. 0040EC44 MOVSX EDX,BL ; EDX = serial[3]
  23. 0040EC47 ADD EAX,EDX ; EAX += serial[3]
  24. 0040EC49 CDQ ; DWORD EAX -> QWORD EDX:EAX
  25. 0040EC4A MOV EDI,0E9 ; EDI = 0xE9
  26. 0040EC4F IDIV EDI ; EAX = EAX / 0xE9 (EDX = resto)
  27. 0040EC51 CMP ECX,4 ; if (strlen(serial) >= 4)
  28. 0040EC54 MOV BYTE PTR SS:[ESP+19],DL ; Salvo il resto nello stack (!IMPORTANTE!)
A parte i soliti controlli inutili abbiamo:
  1. resto[1] = ((serial[6] * 3) + (serial[14] * 2) + serial[4] + serial[3]) % 0xE9;
Proseguiamo:
  1. 0040EC58 JGE SHORT EHSniffe._JUMP_19 ; Sempre verificato
  2. 0040EC5A PUSH 80070057
  3. 0040EC5F CALL EHSniffe.004010D0
  4. _JUMP_19 CMP ECX,2 ; if (strlen(serial) >= 2)
  5. 0040EC67 JGE SHORT EHSniffe._JUMP_20 ; Sempre verificato
  6. 0040EC69 PUSH 80070057
  7. 0040EC6E CALL EHSniffe.004010D0
  8. _JUMP_20 CMP ECX,6 ; if (strlen(serial) >= 6)
  9. 0040EC76 JGE SHORT EHSniffe._JUMP_21 ; Sempre verificato
  10. 0040EC78 PUSH 80070057
  11. 0040EC7D CALL EHSniffe.004010D0
  12. _JUMP_21 CMP ECX,3 ; if (strlen(serial) >= 3)
  13. 0040EC85 JGE SHORT EHSniffe._JUMP_22 ; Sempre verificato
  14. 0040EC87 PUSH 80070057
  15. 0040EC8C CALL EHSniffe.004010D0
  16. _JUMP_22 CMP ECX,0E ; if (strlen(serial) >= 0x0E)
  17. 0040EC94 JGE SHORT EHSniffe._JUMP_23 ; Sempre verificato
  18. 0040EC96 PUSH 80070057
  19. 0040EC9B CALL EHSniffe.004010D0
  20. _JUMP_23 CMP ECX,5 ; if (strlen(serial) >= 5)
  21. 0040ECA3 JGE SHORT EHSniffe._JUMP_24 ; Sempre verificato
  22. 0040ECA5 PUSH 80070057
  23. 0040ECAA CALL EHSniffe.004010D0
  24. _JUMP_24 MOV AL,BYTE PTR DS:[ESI+5] ; AL = serial[5]
  25. 0040ECB2 MOVSX EDX,BYTE PTR DS:[ESI+E] ; EDX = serial[14]
  26. 0040ECB6 MOV BYTE PTR SS:[ESP+17],AL ; Salvo nello stack serial[5]
  27. 0040ECBA MOVSX EAX,AL ; EAX = serial[5]
  28. 0040ECBD ADD EAX,EDX ; EAX += serial[14]
  29. 0040ECBF MOVSX EDX,BL ; EDX = serial[3]
  30. 0040ECC2 ADD EAX,EDX ; EAX += serial[3]
  31. 0040ECC4 MOVSX EDX,BYTE PTR DS:[ESI+6] ; EDX = serial[6]
  32. 0040ECC8 ADD EAX,EDX ; EAX += serial[6]
  33. 0040ECCA MOVSX EDX,BYTE PTR SS:[ESP+4C] ; EDX = serial[2]
  34. 0040ECCF ADD EAX,EDX ; EAX += serial[2]
  35. 0040ECD1 MOVSX EDX,BYTE PTR DS:[ESI+4] ; EDX = serial[4]
  36. 0040ECD5 ADD EAX,EDX ; EAX += serial[4]
  37. 0040ECD7 CDQ ; DWORD EAX -> QWORD EDX:EAX
  38. 0040ECD8 MOV EDI,0D4 ; EDI = 0xD4
  39. 0040ECDD IDIV EDI ; EAX = EAX / 0xD4 (EDX = resto)
  40. 0040ECDF CMP ECX,0D ; if (strlen(serial) >= 0x0D)
  41. 0040ECE2 MOV BYTE PTR SS:[ESP+1A],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Tradotto:
  1. resto[2] = (serial[5] + serial[14] + serial[3] + serial[6] + serial[2] + serial[4]) % 0xD4;
Proseguiamo:
  1. 0040ECE6 JGE SHORT EHSniffe._JUMP_25 ; Sempre verificato
  2. 0040ECE8 PUSH 80070057
  3. 0040ECED CALL EHSniffe.004010D0
  4. _JUMP_25 CMP ECX,0C ; if (strlen(serial) >= 0x0C)
  5. 0040ECF5 JGE SHORT EHSniffe._JUMP_26 ; Sempre verificato
  6. 0040ECF7 PUSH 80070057
  7. 0040ECFC CALL EHSniffe.004010D0
  8. _JUMP_26 CMP ECX,4 ; if (strlen(serial) >= 4)
  9. 0040ED04 MOV AL,BYTE PTR DS:[ESI+C] ; AL = serial[12]
  10. 0040ED07 MOV BYTE PTR SS:[ESP+14],AL ; Salvo nello stack serial[12]
  11. 0040ED0B JGE SHORT EHSniffe._JUMP_27 ; Sempre verificato
  12. 0040ED0D PUSH 80070057
  13. 0040ED12 CALL EHSniffe.004010D0
  14. _JUMP_27 MOVSX EDX,BYTE PTR SS:[ESP+14] ; EDX = serial[12]
  15. 0040ED1C MOVSX EAX,BYTE PTR DS:[ESI+4] ; EAX = serial[4]
  16. 0040ED20 IMUL EAX,EDX ; EAX *= EDX
  17. 0040ED23 MOVSX EDX,BYTE PTR DS:[ESI+D] ; EDX = serial[13]
  18. 0040ED27 ADD EAX,EDX ; EAX += serial[13]
  19. 0040ED29 CDQ ; DWORD EAX -> QWORD EDX:EAX
  20. 0040ED2A MOV EDI,7B ; EDI = 0x7B
  21. 0040ED2F IDIV EDI ; EAX = EAX / 0x7B (EDX = resto)
  22. 0040ED31 CMP ECX,0C ; if (strlen(serial) >= 0x0C)
  23. 0040ED34 MOV BYTE PTR SS:[ESP+1B],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Tradotto:
  1. resto[3] = (serial[12] * serial[4] + serial[13]) % 0x7B;
Il codice ora si complica un pò, ma fa sempre la stessa cosa, salva un resto sullo stack:
  1.  
  2. 0040ED38 JGE SHORT EHSniffe._JUMP_28 ; Sempre verificato
  3. 0040ED3A PUSH 80070057
  4. 0040ED3F CALL EHSniffe.004010D0
  5. _JUMP_28 CMP ECX,3 ; if (strlen(serial) >= 3)
  6. 0040ED47 JGE SHORT EHSniffe._JUMP_29 ; Sempre verificato
  7. 0040ED49 PUSH 80070057
  8. 0040ED4E CALL EHSniffe.004010D0
  9. _JUMP_29 CMP ECX,0D ; if (strlen(serial) >= 0x0D)
  10. 0040ED56 JGE SHORT EHSniffe._JUMP_30 ; Sempre verificato
  11. 0040ED58 PUSH 80070057
  12. 0040ED5D CALL EHSniffe.004010D0
  13. _JUMP_30 CMP ECX,2 ; if (strlen(serial) >= 2)
  14. 0040ED65 JGE SHORT EHSniffe._JUMP_31 ; Sempre verificato
  15. 0040ED67 PUSH 80070057
  16. 0040ED6C CALL EHSniffe.004010D0
  17. _JUMP_31 CMP ECX,8 ; if (strlen(serial) >= 8)
  18. 0040ED74 JGE SHORT EHSniffe._JUMP_32 ; Sempre verificato
  19. 0040ED76 PUSH 80070057
  20. 0040ED7B CALL EHSniffe.004010D0
  21. _JUMP_32 CMP ECX,6 ; if (strlen(serial) >= 6)
  22. 0040ED83 MOV AL,BYTE PTR DS:[ESI+8] ; AL = serial[8]
  23. 0040ED86 MOV BYTE PTR SS:[ESP+13],AL ; Salvo nello stack serial[8]
  24. 0040ED8A JGE SHORT EHSniffe._JUMP_33 ; Sempre verificato
  25. 0040ED8C PUSH 80070057
  26. 0040ED91 CALL EHSniffe.004010D0
  27. _JUMP_33 CMP ECX,0A ; if (strlen(serial) >= 0x0A)
  28. 0040ED99 JGE SHORT EHSniffe._JUMP_34 ; Sempre verificato
  29. 0040ED9B PUSH 80070057
  30. 0040EDA0 CALL EHSniffe.004010D0
  31. _JUMP_34 CMP ECX,0B ; if (strlen(serial) >= 0x0B)
  32. 0040EDA8 JGE SHORT EHSniffe._JUMP_35 ; Sempre verificato
  33. 0040EDAA PUSH 80070057
  34. 0040EDAF CALL EHSniffe.004010D0
  35. _JUMP_35 CMP ECX,0E ; if (strlen(serial) >= 0x0E)
  36. 0040EDB7 MOV DL,BYTE PTR DS:[ESI+B] ; DL = serial[11]
  37. 0040EDBA MOV BYTE PTR SS:[ESP+15],DL ; Salvo nello stack serial[11]
  38. 0040EDBE JGE SHORT EHSniffe._JUMP_36 ; Sempre verificato
  39. 0040EDC0 PUSH 80070057
  40. 0040EDC5 CALL EHSniffe.004010D0
  41. _JUMP_36 MOVSX EDX,BYTE PTR DS:[ESI+E] ; EDX = serial[14]
  42. 0040EDCE MOVSX EAX,BYTE PTR SS:[ESP+15] ; EAX = serial[11]
  43. 0040EDD3 LEA EAX,DWORD PTR DS:[EDX+EAX*2] ; EAX = EDX + EAX * 2
  44. 0040EDD6 MOVSX EDX,BYTE PTR DS:[ESI+6] ; EDX = serial[6]
  45. 0040EDDA IMUL EDX,EDX,7 ; EDX *= 7
  46. 0040EDDD LEA EAX,DWORD PTR DS:[EDX+EAX*2] ; EAX = EDX + EAX * 2
  47. 0040EDE0 MOVSX EDX,BYTE PTR SS:[ESP+4C] ; EDX = serial[2]
  48. 0040EDE5 LEA EDX,DWORD PTR DS:[EDX+EDX*8] ; EDX *= 9
  49. 0040EDE8 ADD EAX,EDX ; EAX += EDX
  50. 0040EDEA MOVSX EDX,BYTE PTR DS:[ESI+A] ; EDX = serial[10]
  51. 0040EDEE ADD EAX,EDX ; EAX += EDX
  52. 0040EDF0 MOVSX EDX,BYTE PTR SS:[ESP+13] ; EDX = serial[8]
  53. 0040EDF5 ADD EAX,EDX ; EAX += serial[8]
  54. 0040EDF7 MOVSX EDX,BYTE PTR DS:[ESI+D] ; EDX = serial[13]
  55. 0040EDFB ADD EAX,EDX ; EAX += serial[13]
  56. 0040EDFD MOVSX EDX,BL ; EDX = serial[3]
  57. 0040EE00 ADD EAX,EDX ; EAX += serial[3]
  58. 0040EE02 MOVSX EDX,BYTE PTR SS:[ESP+14] ; EDX = serial[12]
  59. 0040EE07 ADD EAX,EDX ; EAX += serial[13]
  60. 0040EE09 CDQ ; DWORD EAX -> QWORD EDX:EAX
  61. 0040EE0A MOV EDI,0DA ; EDI = 0xDA
  62. 0040EE0F IDIV EDI ; EAX = EAX / 0xDA (EDX = resto)
  63. 0040EE11 CMP ECX,2 ; if (strlen(serial) >= 2)
  64. 0040EE14 MOV BYTE PTR SS:[ESP+1C],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Tradotto:
  1. resto[4] = (((serial[11] * 2 + serial[14]) * 2) + (serial[6] * 7) + (serial[2] * 9)
  2. + serial[10] + serial[8] + serial[13] + serial[3] + serial[12]) % 0xDA;
Proseguiamo:
  1.  
  2. 0040EE18 JGE SHORT EHSniffe._JUMP_37 ; Sempre verificato
  3. 0040EE1A PUSH 80070057
  4. 0040EE1F CALL EHSniffe.004010D0
  5. _JUMP_37 CMP ECX,6 ; if (strlen(serial) >= 6)
  6. 0040EE27 JGE SHORT EHSniffe._JUMP_38 ; Sempre verificato
  7. 0040EE29 PUSH 80070057
  8. 0040EE2E CALL EHSniffe.004010D0
  9. _JUMP_38 CMP ECX,4 ; if (strlen(serial) >= 4)
  10. 0040EE36 JGE SHORT EHSniffe._JUMP_39 ; Sempre verificato
  11. 0040EE38 PUSH 80070057
  12. 0040EE3D CALL EHSniffe.004010D0
  13. _JUMP_39 CMP ECX,3 ; if (strlen(serial) >= 3)
  14. 0040EE45 JGE SHORT EHSniffe._JUMP_40 ; Sempre verificato
  15. 0040EE47 PUSH 80070057
  16. 0040EE4C CALL EHSniffe.004010D0
  17. _JUMP_40 CMP ECX,7 ; if (strlen(serial) >= 7)
  18. 0040EE54 JGE SHORT EHSniffe._JUMP_41 ; Sempre verificato
  19. 0040EE56 PUSH 80070057
  20. 0040EE5B CALL EHSniffe.004010D0
  21. _JUMP_41 CMP ECX,8 ; if (strlen(serial) >= 8)
  22. 0040EE63 MOV AL,BYTE PTR DS:[ESI+7] ; AL = serial[7]
  23. 0040EE66 JGE SHORT EHSniffe._JUMP_42 ; Sempre verificato
  24. 0040EE68 PUSH 80070057
  25. 0040EE6D CALL EHSniffe.004010D0
  26. _JUMP_42 CMP ECX,2 ; if (strlen(serial) >= 2)
  27. 0040EE75 JGE SHORT EHSniffe._JUMP_43 ; Sempre verificato
  28. 0040EE77 PUSH 80070057
  29. 0040EE7C CALL EHSniffe.004010D0
  30. _JUMP_43 MOVSX EDX,BYTE PTR DS:[ESI+6] ; EDX = serial[6]
  31. 0040EE85 MOVSX EAX,AL ; EAX = serial[7]
  32. 0040EE88 LEA EDX,DWORD PTR DS:[EDX+EAX*4] ; EDX = EDX + EAX * 4
  33. 0040EE8B MOVSX EAX,BYTE PTR DS:[ESI+4] ; EAX = serial[4]
  34. 0040EE8F LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; EAX *= 3
  35. 0040EE92 LEA EAX,DWORD PTR DS:[EAX+EDX*2] ; EAX = EAX + EDX * 2
  36. 0040EE95 MOVSX EDX,BYTE PTR SS:[ESP+4C] ; EDX = serial[2]
  37. 0040EE9A ADD EAX,EDX ; EAX += serial[2]
  38. 0040EE9C MOVSX EDX,BYTE PTR SS:[ESP+13] ; EDX = serial[8]
  39. 0040EEA1 ADD EAX,EDX ; EAX += serial[9]
  40. 0040EEA3 MOVSX EDX,BL ; EDX = serial[3]
  41. 0040EEA6 ADD EAX,EDX ; EAX += serial[3]
  42. 0040EEA8 MOVSX EDX,BYTE PTR SS:[ESP+4C] ; EDX = serial[2]
  43. 0040EEAD ADD EAX,EDX ; EAX += serial[2]
  44. 0040EEAF CDQ ; DWORD EAX -> QWORD EDX:EAX
  45. 0040EEB0 MOV EDI,0D3 ; EDI = 0xD3
  46. 0040EEB5 IDIV EDI ; EAX = EAX / 0xD3 (EDX = resto)
  47. 0040EEB7 CMP ECX,5 ; if (strlen(serial) >= 5)
  48. 0040EEBA MOV BYTE PTR SS:[ESP+1D],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Tradotto:
  1. resto[5] = ((serial[4] * 3) + (serial[6] + serial[7] * 4) * 2
  2. + serial[2] + serial[8] + serial[3] + serial[2]) % 0xD3;
Proseguiamo:
  1.  
  2. 0040EEBE JGE SHORT EHSniffe._JUMP_44 ; Sempre verificato
  3. 0040EEC0 PUSH 80070057
  4. 0040EEC5 CALL EHSniffe.004010D0
  5. _JUMP_44 CMP ECX,8 ; if (strlen(serial) >= 8)
  6. 0040EECD JGE SHORT EHSniffe._JUMP_45 ; Sempre verificato
  7. 0040EECF PUSH 80070057
  8. 0040EED4 CALL EHSniffe.004010D0
  9. _JUMP_45 CMP ECX,2 ; if (strlen(serial) >= 2)
  10. 0040EEDC JGE SHORT EHSniffe._JUMP_46 ; Sempre verificato
  11. 0040EEDE PUSH 80070057
  12. 0040EEE3 CALL EHSniffe.004010D0
  13. _JUMP_46 CMP ECX,9 ; if (strlen(serial) >= 9)
  14. 0040EEEB JGE SHORT EHSniffe._JUMP_47 ; Sempre verificato
  15. 0040EEED PUSH 80070057
  16. 0040EEF2 CALL EHSniffe.004010D0
  17. _JUMP_47 CMP ECX,3 ; if (strlen(serial) >= 3)
  18. 0040EEFA MOV AL,BYTE PTR DS:[ESI+9] ; AL = 10 carattere
  19. 0040EEFD MOV BYTE PTR SS:[ESP+16],AL ; Salvo nello stack il 10 carattere
  20. 0040EF01 JGE SHORT EHSniffe._JUMP_48 ; Sempre verificato
  21. 0040EF03 PUSH 80070057
  22. 0040EF08 CALL EHSniffe.004010D0
  23. _JUMP_48 MOVSX EAX,BL ; EAX = serial[3]
  24. 0040EF10 LEA EDX,DWORD PTR DS:[EAX+EAX*2] ; EDX *= 3
  25. 0040EF13 MOVSX EAX,BYTE PTR SS:[ESP+16] ; EAX = serial[9]
  26. 0040EF18 LEA EAX,DWORD PTR DS:[EDX+EAX*4] ; EAX = EDX + EAX *4
  27. 0040EF1B MOVSX EDX,BYTE PTR SS:[ESP+4C] ; EDX = serial[2]
  28. 0040EF20 IMUL EDX,EDX,0B ; EDX *= 0x0B
  29. 0040EF23 ADD EAX,EDX ; EAX += EDX
  30. 0040EF25 MOVSX EDX,BYTE PTR SS:[ESP+17] ; EDX = serial[5]
  31. 0040EF2A IMUL EDX,EDX,7 ; EDX *= 7
  32. 0040EF2D ADD EAX,EDX ; EAX += EDX
  33. 0040EF2F MOVSX EDX,BYTE PTR SS:[ESP+13] ; EDX = serial[8]
  34. 0040EF34 ADD EAX,EDX ; EAX += serial[8]
  35. 0040EF36 CDQ ; DWORD EAX -> QWORD EDX:EAX
  36. 0040EF37 MOV ESI,0F4 ; ESI = 0xF4
  37. 0040EF3C IDIV ESI ; EAX = EAX / 0xF4 (EDX = resto)
  38. 0040EF3E CMP ECX,3 ; if (strlen(serial) >= 3)
  39. 0040EF41 MOV BYTE PTR SS:[ESP+1E],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Tradotto:
  1. resto[6] = (((serial[3] * 3) + serial[9] * 4) + (serial[2] * 0xB) + (serial[5] * 7) + serial[8])
  2. % 0xF4;
Vediamo ora l'ultimo di questi 8 resti:
  1. 0040EF45 JGE SHORT EHSniffe._JUMP_49 ; Sempre verificato
  2. 0040EF47 PUSH 80070057
  3. 0040EF4C CALL EHSniffe.004010D0
  4. _JUMP_49 CMP ECX,0C ; if (strlen(serial) >= 0x0C)
  5. 0040EF54 JGE SHORT EHSniffe._JUMP_50 ; Sempre verificato
  6. 0040EF56 PUSH 80070057
  7. 0040EF5B CALL EHSniffe.004010D0
  8. _JUMP_50 CMP ECX,0B ; if (strlen(serial) >= 0x0B)
  9. 0040EF63 JGE SHORT EHSniffe._JUMP_51 ; Sempre verificato
  10. 0040EF65 PUSH 80070057
  11. 0040EF6A CALL EHSniffe.004010D0
  12. _JUMP_51 CMP ECX,9 ; if (strlen(serial) >= 9)
  13. 0040EF72 JGE SHORT EHSniffe._JUMP_52 ; Sempre verificato
  14. 0040EF74 PUSH 80070057
  15. 0040EF79 CALL EHSniffe.004010D0
  16. _JUMP_52 CMP ECX,2 ; if (strlen(serial) >= 2)
  17. 0040EF81 JGE SHORT EHSniffe._JUMP_53 ; Sempre verificato
  18. 0040EF83 PUSH 80070057
  19. 0040EF88 CALL EHSniffe.004010D0
  20. _JUMP_53 CMP ECX,3 ; if (strlen(serial) >= 3)
  21. 0040EF90 JGE SHORT EHSniffe._JUMP_54 ; Sempre verificato
  22. 0040EF92 PUSH 80070057
  23. 0040EF97 CALL EHSniffe.004010D0
  24. _JUMP_54 MOVSX EAX,BYTE PTR SS:[ESP+15] ; EAX = serial[11]
  25. 0040EFA1 MOVSX ECX,BL ; ECX = serial[3]
  26. 0040EFA4 LEA EDX,DWORD PTR DS:[ECX+EAX*2] ; EDX = ECX + EAX * 2
  27. 0040EFA7 MOVSX EAX,BYTE PTR SS:[ESP+4C] ; EAX = serial[2]
  28. 0040EFAC MOVSX ECX,BYTE PTR SS:[ESP+16] ; ECX = serial[9] (perdo strlen(serial)!)
  29. 0040EFB1 LEA EAX,DWORD PTR DS:[EAX+EDX*2] ; EAX = EAX + EDX * 2
  30. 0040EFB4 IMUL ECX,ECX,7 ; ECX *= 7
  31. 0040EFB7 MOVSX EDX,BYTE PTR SS:[ESP+14] ; EDX = serial[12]
  32. 0040EFBC IMUL EDX,EDX,0B ; EDX *= 0x0B
  33. 0040EFBF LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; EAX *= 3
  34. 0040EFC2 ADD EAX,ECX ; EAX += ECX
  35. 0040EFC4 ADD EAX,EDX ; EAX += EDX
  36. 0040EFC6 MOVSX ECX,BL ; ECX = serial[3]
  37. 0040EFC9 ADD EAX,ECX ; EAX += serial[3]
  38. 0040EFCB CDQ ; DWORD EAX -> QWORD EDX:EAX
  39. 0040EFCC MOV ECX,7B ; ECX = 0x7B
  40. 0040EFD1 IDIV ECX ; EAX = EAX / 0x7B (EDX = resto)
  41. 0040EFD3 XOR ESI,ESI ; ESI = 0 (perdo serial!)
  42. 0040EFD5 MOV BYTE PTR SS:[ESP+1F],DL ; Salvo il resto nello stack (!IMPORTANTE!)
Tradotto:
  1. resto[7] = (((serial[2] + (serial[3] + serial[11] * 2) * 2) * 3) + (serial[9] * 7)
  2. + (serial[12] * 0xB) + serial[3]) % 0x7B;
Abbiamo finito di calcolare e di tradurre il codice degli 8 resti. Siamo ormai "prossimi" alla fine. Andiamo ora ad analizzare l'ultima parte dell'algoritmo, capendo quello che il programma fa con questi 8 valori:
  1. 0040EFD9 LEA ESP,DWORD PTR SS:[ESP] ; Sistemo lo stackpointer ! Inizio ciclo !
  2. 0040EFE0 CMP EBP,ESI ; EBP = 0x171E, ESI = contatore 0-7
  3. 0040EFE2 JLE SHORT EHSniffe.0040EFED ; if (EBP > ESI)
  4. 0040EFE4 MOV EDI,EBP ; Imposto EDI in base a questo controllo
  5. 0040EFE6 SUB EDI,ESI
  6. 0040EFE8 ADD EDI,59 ; EDI = EBP - ESI + 0x59
  7. 0040EFEB JMP SHORT EHSniffe._JUMP_55
  8. 0040EFED MOV EDI,ESI ; else (*)
  9. 0040EFEF SUB EDI,EBP
  10. 0040EFF1 ADD EDI,12 ; EDI = ESI - EBP + 0x12
  11. _JUMP_55 CMP EBP,ESI ; EBP = 0x171E, ESI = contatore 0-7
  12. 0040EFF6 JLE SHORT EHSniffe._JUMP_56 ; if (EBP > ESI)
  13. 0040EFF8 MOV EAX,EBP ; Imposto EAX in base a questo controllo
  14. 0040EFFA SUB EAX,ESI
  15. 0040EFFC ADD EAX,3 ; EAX = EBP - ESI + 3
  16. 0040EFFF JMP SHORT EHSniffe._JUMP_57
  17. _JUMP_56 MOV EAX,ESI ; else (*)
  18. 0040F003 SUB EAX,EBP
  19. 0040F005 ADD EAX,12 ; EAX = ESI - EBP + 0x12
  20. _JUMP_57 CDQ ; DWORD EAX -> QWORD EDX:EAX
  21. 0040F009 MOV ECX,7 ; ECX = 7
  22. 0040F00E IDIV ECX ; EAX = EAX / 7 (EDX resto)
  23. 0040F010 XOR EBX,EBX ; EBX = 0
  24. 0040F012 MOV BL,BYTE PTR SS:[ESP+ESI+18] ; EBX = resto[ESI]
  25. 0040F016 PUSH EBX ; Passo resto[ESI] alla funzione
  26. 0040F017 CALL DWORD PTR SS:[ESP+EDX*4+24] ; !Attenzione, funzioni variabili!
  27. 0040F01B MOV DWORD PTR SS:[ESP+50],EAX ; Salvo nello stack il valore di ritorno
  28. 0040F01F MOV EAX,EDI ; EAX = EDI
  29. 0040F021 CDQ ; DWORD EAX -> QWORD EDX:EAX
  30. 0040F022 MOV ECX,7 ; ECX = 7
  31. 0040F027 IDIV ECX ; EAX = EAX / 7 (EDX resto)
  32. 0040F029 PUSH EBX ; Passo resto[ESI] alla funzione
  33. 0040F02A CALL DWORD PTR SS:[ESP+EDX*4+28] ; !Attenzione, funzioni variabili!
  34. 0040F02E MOV ECX,DWORD PTR SS:[ESP+54] ; ECX = Il valore di ritono della 1 call
  35. 0040F032 ADD EAX,ECX ; EAX += ECX (Sommo i valori modificati)
  36. 0040F034 CDQ ; DWORD EAX -> QWORD EDX:EAX
  37. 0040F035 MOV ECX,252E ; ECX = 0x252E
  38. 0040F03A IDIV ECX ; EAX = EAX / 0x252E (EDX resto)
  39. 0040F03C ADD ESP,8 ; Sistemo lo stackpointer
  40. 0040F03F ADD EBP,EDX ; ! EBP += il valore calcolato !
  41. 0040F041 INC ESI ; ESI += 1 (Contatore)
  42. 0040F042 CMP ESI,8 ; if (ESI != 8)
  43. 0040F045 JL SHORT EHSniffe.0040EFE0 ; Rinizio ciclo
Non dobrebbe essere difficile capire il codice commentato, comunque quello che fa questo codice in parole povere è:
1) Confrontare il valore attuale di EBX con il contatore (EBX era stato impostato molto prima a 0x171E ricordate?)
2) In base a questo confronto calcolare due valori, EAX e EDI
3) Viene calcolato un numero, compreso da 0 a 6 in base al resto della divisione di questi due valori per ECX (7)
4) Questo numero determina quale funzione (per un totale quindi di 7 funzioni diverse) andrà a lavorare con l'attuale valore di resto[ESI]
5) Vengono sommati insieme i due valori del resto[ESI] modificati dalle funzioni e ne viene calcolato il resto della divisione per 0x252E
6) Questo resto viene aggiunto al vecchio valore di EBP
Vale la pena spendere altre due parole su questo pezzetto di codice.
Il controllo iniziale che si fa in ogni ciclo, dove si controlla EBP con ESI, è un controllo praticamente inutile in quanto si confronta un valore estremamente grande con un contatore che varia da 0 a 7, non sarà quindi mai eseguito il ramo else di questo controllo (tranne su owerflow di EBP).
L'altro punto sul quale occorre porre attenzione sono le chiamate alle routine variabili; occorre infatti col debugger cercare tutte queste 7 funzioni, il cui indirizzo sarà dato da CALL DWORD PTR SS:[ESP+EDX*4+24] (o da CALL DWORD PTR SS:[ESP+EDX*4+24] in base allo stato attuale dello stackpointer prima o dopo la prima call) al variare di EDX da 0 a 6 (resto della divisione per 7).
Quello che andremo quindi a fare ora prima di proseguire sarà cercare queste 7 routine e reversarle, in modo da avere un codice ad alto livello funzionante per tutti i possibili casi di input.
Fortunatamente l'assembly di queste routine è molto breve e di facile comprensione. Lo riporto di seguito:
  1. ; Prima funzione
  2. 0040E290 MOVSX EAX,BYTE PTR SS:[ESP+4] ; EAX = resto[ESI]
  3. 0040E295 LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; EAX *= 3
  4. 0040E298 CDQ ; DWORD EAX -> QWORD EDX:EAX
  5. 0040E299 MOV ECX,3A ; ECX = 0x3A
  6. 0040E29E IDIV ECX
  7. 0040E2A0 MOV EAX,EDX ; EAX = EAX % 0x3A
  8. 0040E2A2 ADD EAX,378 ; EAX = EAX + 0x378
  9. ; Seconda funzione
  10. 0040E2B0 MOVSX ECX,BYTE PTR SS:[ESP+4] ; ECX = resto[ESI]
  11. 0040E2B5 LEA EAX,DWORD PTR DS:[ECX+ECX+16522] ; EAX = ECX * 2 + 0x16522
  12. 0040E2BC CDQ ; DWORD EAX -> QWORD EDX:EAX
  13. 0040E2BD IDIV ECX
  14. 0040E2BF MOV EAX,EDX ; EAX = EAX % ECX
  15. 0040E2C1 RETN
  16. ; Terza funzione
  17. 0040E2D0 MOVSX EAX,BYTE PTR SS:[ESP+4] ; EAX = resto[ESI]
  18. 0040E2D5 ADD EAX,945 ; EAX = EAX + 0x945
  19. ; Quarta funzione
  20. 0040E2E0 MOVSX EAX,BYTE PTR SS:[ESP+4] ; EAX = resto[ESI]
  21. 0040E2E5 IMUL EAX,EAX,7 ; EAX *= 7
  22. 0040E2E8 ADD EAX,84E ; EAX += 0x84E
  23. 0040E2ED CDQ ; DWORD EAX -> QWORD EDX:EAX
  24. 0040E2EE MOV ECX,0FD ; ECX = 0x0FD
  25. 0040E2F3 IDIV ECX
  26. 0040E2F5 MOV EAX,EDX ; EAX = EAX % 0x0FD
  27. 0040E2F7 RETN
  28. ; Quinta funzione
  29. 0040E300 MOVSX EAX,BYTE PTR SS:[ESP+4] ; EAX = resto[ESI]
  30. 0040E305 ADD EAX,2159 ; EAX += 0x2159
  31. 0040E30A CDQ ; DWORD EAX -> QWORD EDX:EAX
  32. 0040E30B MOV ECX,0A26 ; ECX = 0xA26
  33. 0040E310 IDIV ECX
  34. 0040E312 MOV EAX,EDX ; EAX = EAX % 0x0A26
  35. 0040E314 RETN
  36. ; Sesta funzione
  37. 0040E320 MOVSX EAX,BYTE PTR SS:[ESP+4] ; EAX = resto[ESI]
  38. 0040E325 SUB EAX,4F ; EAX -= 0x4F
  39. 0040E328 RETN
  40. ; Settima funzione
  41. 0040E330 MOVSX EAX,BYTE PTR SS:[ESP+4] ; EAX = resto[ESI]
  42. 0040E335 ADD EAX,78 ; EAX += 0x78
  43. 0040E338 RETN
Traduciamo prima queste funzioni in C:
  1. long f1(long resto)
  2. {
  3. if (resto >= 0x80)
  4. resto = resto | 0xFFFFFF00;
  5. return ((resto * 3) % 0x3A) + 0x378;
  6. }
  7.  
  8. long f2(long resto)
  9. {
  10. if (resto >= 0x80)
  11. resto = resto | 0xFFFFFF00;
  12. return (resto * 2 + 0x16522) % resto;
  13. }
  14.  
  15. long f3(long resto)
  16. {
  17. if (resto >= 0x80)
  18. resto = resto | 0xFFFFFF00;
  19. return resto + 0x945;
  20. }
  21.  
  22. long f4(long resto)
  23. {
  24. if (resto >= 0x80)
  25. resto = resto | 0xFFFFFF00;
  26. return (resto * 7 + 0x84E) % 0x0FD;
  27. }
  28.  
  29. long f5(long resto)
  30. {
  31. if (resto >= 0x80)
  32. resto = resto | 0xFFFFFF00;
  33. return (resto + 0x2159) % 0x0A26;
  34. }
  35.  
  36. long f6(long resto)
  37. {
  38. if (resto >= 0x80)
  39. resto = resto | 0xFFFFFF00;
  40. return resto - 0x4F;
  41. }
  42.  
  43. long f7(long resto)
  44. {
  45. if (resto >= 0x80)
  46. resto = resto | 0xFFFFFF00;
  47. return resto + 0x78;
  48. }
l'if che ho inserito all'interno di ogni funzione serve per simulare l'istruzione MOVSX, controllo in fatti che il valore di resto[ESI] passato non sia negativo (>= 0x80) e se lo è viene espanso il bit di segno (0xF) per tutti i 6 bit restanti del registro.
Vediamo ora il codice del ciclo di prima che utilizza queste funzioni e i resti calcolati in precedenza:
  1. long (*p[7])(long) = { f1,f2,f3,f4,f5,f6,f7 }; /* Array puntatori a funzione */
  2. EBP = 0x171E; /* Valore iniziale */
  3.  
  4. for (ESI = 0; ESI < 8; ESI++)
  5. {
  6. if (EBP > ESI)
  7. {
  8. EDI = EBP - ESI + 0x59;
  9. EAX = EBP - ESI + 0x03;
  10. } else { /* Ramo mai eseguito */
  11. EDI = ESI - EBP + 0x12;
  12. EAX = ESI - EBP + 0x12;
  13. }
  14.  
  15. FunzOffset = EAX % 7;
  16. EAX = p[FunzOffset](resto[ESI]); /* Evito di fare uno switch-case */
  17.  
  18. Stack = EAX; /* Salvo il primo resto modificato*/
  19.  
  20. FunzOffset = EDI % 7;
  21. EAX = p[FunzOffset](resto[ESI]); /* Evito di fare uno switch-case */
  22.  
  23. EAX += Stack; /* Aggiungo a EAX il valore salvato */
  24. EBP += EAX % 0x252E;
  25. } /* Fine ciclo */
Con questo abbiamo praticamente terminato l'anlisi del codice, manca l'ultima parte del controllo sull'EBP calcolato che andrà a decidere se il seriale letto in input è corretto o meno.
Il codice ora è molto dispersivo e vengono effettuato varie call che non ci interessano, il disassemblato completo è:
  1. 0040F047 CALL EHSniffe.0043BE26 ; viene settato EAX (non ci interessa)
  2. 0040F04C MOV EDX,DWORD PTR DS:[EAX] ; EDX = indirizzo punato da EAX
  3. 0040F04E MOV ECX,EAX ; ECX = EAX
  4. 0040F050 CALL DWORD PTR DS:[EDX+C] ; Non ci interessa
  5. 0040F053 ADD EAX,10
  6. 0040F056 MOV DWORD PTR SS:[ESP+4C],EAX
  7. 0040F05A PUSH EBP
  8. 0040F05B LEA EAX,DWORD PTR SS:[ESP+50]
  9. 0040F05F PUSH EHSniffe.0045C168 ; ASCII "count=%d"
  10. 0040F064 PUSH EAX
  11. 0040F065 MOV DWORD PTR SS:[ESP+50],0
  12. 0040F06D CALL EHSniffe.004018E0 ; !Questa chiamate rimposta EBP al valore calcolato!
  13. 0040F072 ADD ESP,0C
  14. 0040F075 CMP EBP,2BA5 ; if (EBP == 0x2BA5)
  15. 0040F07B JE SHORT EHSniffe._JUMP_OK ; Salta
  16. 0040F07D CMP EBP,3A30 ; if (EBP == 0x3A30)
  17. 0040F083 JE SHORT EHSniffe._JUMP_OK ; Salta
  18. 0040F085 MOV EAX,DWORD PTR SS:[ESP+4C]
  19. 0040F089 ADD EAX,-10 ; "count=11031"
  20. 0040F08C MOV DWORD PTR SS:[ESP+44],-1
  21. 0040F094 LEA ECX,DWORD PTR DS:[EAX+C]
  22. 0040F097 OR EDX,FFFFFFFF
  23. 0040F09A LOCK XADD DWORD PTR DS:[ECX],EDX ; LOCK prefix
  24. 0040F09E DEC EDX
  25. 0040F09F TEST EDX,EDX
  26. 0040F0A1 JG SHORT EHSniffe.0040F0AB
  27. 0040F0A3 MOV ECX,DWORD PTR DS:[EAX]
  28. 0040F0A5 MOV EDX,DWORD PTR DS:[ECX]
  29. 0040F0A7 PUSH EAX
  30. 0040F0A8 CALL DWORD PTR DS:[EDX+4] ; Non ci interessa
  31. 0040F0AB POP EDI
  32. 0040F0AC POP EBX
  33. 0040F0AD POP EBP
  34. 0040F0AE XOR EAX,EAX ; EAX = 0, serial errato
  35. 0040F0B0 POP ESI
  36. 0040F0B1 MOV ECX,DWORD PTR SS:[ESP+2C]
  37. 0040F0B5 MOV DWORD PTR FS:[0],ECX
  38. 0040F0BC ADD ESP,38
  39. 0040F0BF RETN 4 ; Ritono EAX = 0
  40. _JUMP_OK MOV EAX,DWORD PTR SS:[ESP+4C] ; Salto qui solo se EBP == 0x2BA5 o EBP == 0x3A30
  41. 0040F0C6 ADD EAX,-10 ; EAX -= 10
  42. 0040F0C9 MOV DWORD PTR SS:[ESP+44],-1
  43. 0040F0D1 LEA ECX,DWORD PTR DS:[EAX+C]
  44. 0040F0D4 OR EDX,FFFFFFFF
  45. 0040F0D7 LOCK XADD DWORD PTR DS:[ECX],EDX ; LOCK prefix
  46. 0040F0DB DEC EDX
  47. 0040F0DC TEST EDX,EDX
  48. 0040F0DE JG SHORT EHSniffe.0040F0E8
  49. 0040F0E0 MOV ECX,DWORD PTR DS:[EAX]
  50. 0040F0E2 MOV EDX,DWORD PTR DS:[ECX]
  51. 0040F0E4 PUSH EAX
  52. 0040F0E5 CALL DWORD PTR DS:[EDX+4] ; Non ci interessa
  53. 0040F0E8 MOV ECX,DWORD PTR SS:[ESP+3C]
  54. 0040F0EC POP EDI
  55. 0040F0ED POP EBX
  56. 0040F0EE POP EBP
  57. 0040F0EF MOV EAX,1
  58. 0040F0F4 POP ESI
  59. 0040F0F5 MOV DWORD PTR FS:[0],ECX
  60. 0040F0FC ADD ESP,38
  61. 0040F0FF RETN 4 ; Ritorno EAX != 0
Da quello che avevamo visto prima di addentrarci in questa routine CheckSerial alla fine di tutto quanto viene controllato il valore di EAX e viene stampato il messaggion di serial errato se questo valore è uguale a 0.
Quindi in conclusione il nostro input è giusto solo se ha generato un EBP == 0x2BA5 o EBP == 0x3A30. In C:
  1. if (EBP == 0x2BA5 || EBP == 0x3A30)
  2. printf("Serial Esatto\n");
  3. else
  4. printf("Serial Errato\n");
Il reversing vero e proprio del codice è terminato, dopo un bel pò di lavoro siamo riusciti a tradurre completamente l'algoritmo di controllo e siamo ora in grado di patcharlo e realizzare un keygen completo.
(L'algoritmo di check è scaricabile dalla di questo articolo)


Script Execution Time: 0.394305 seconds - Visite: 640638
Copyright © 2007-2017 Suondmao v0.1.5-1