简单逆向练习
passkey¶
C
#include <stdio.h>
#include <string.h>
int checkpass(const char* passkey);
int main() {
// user input for password
char passkey[100];
printf("Enter your password: ");
scanf("%99s", passkey);
checkpass(passkey);
return 0;
}
int checkpass(const char* passkey) {
int minLength = 6;
int maxLength = 20;
if (strlen(passkey) < minLength || strlen(passkey) > maxLength) {
printf("Password length must be between %d and %d characters.\n", minLength, maxLength);
return 0;
}
// define xor key
const char* xorKey = "mysecretkey";
// define correct password
const char* correctPassword = "securepassword";
// xor ecrypt the input password and compare with correct password
for (int i = 0; i < strlen(correctPassword); i++) {
if ((passkey[i] ^ xorKey[i % strlen(xorKey)]) != correctPassword[i]) {
printf("Incorrect password.\n");
return 0;
}
}
return 1;
}
编译

首先找到主函数,现在我们想要破解该程序,有两种思路,第一种是找到正确的key,第二种是修改程序的判断逻辑,现在将分别基于这两种方法进行操作
方法一(基于伪C代码)¶
首先将反汇编转换为伪C代码
C
int __cdecl main(int argc, const char **argv, const char **envp)
{
char Str[100]; // [esp+1Ch] [ebp-64h] BYREF
__main();
printf("Enter your password: ");
scanf("%99s", Str);
checkpass(Str);
return 0;
}
显然核心逻辑在于checkpass函数,我们查看checkpass函数的伪C代码
C
int __cdecl checkpass(char *Str)
{
size_t i; // eax
size_t v3; // [esp+3Ch] [ebp-Ch]
if ( strlen(Str) >= 6 && strlen(Str) <= 0x14 )
{
v3 = 0;
for ( i = strlen("securepassword"); v3 < i; i = strlen("securepassword") )
{
if ( ((unsigned __int8)aMysecretkey[v3 % strlen("mysecretkey")] ^ (unsigned __int8)Str[v3]) != aSecurepassword[v3] )
{
puts("Incorrect password.");
return 0;
}
++v3;
}
return 1;
}
else
{
printf("Password length must be between %d and %d characters.\n", 6, 20);
return 0;
}
}
我们将这两段代码结合一下,放在代码编辑器中查看

显然存在很多报错,我们一步步尝试一步步还原代码:
- 首先补全头文件
可以看到使用了printf和strlen函数,那么需要补充如下头文件
- 补全缺失的变量(aSecurepassword, aMysecretkey)
根据代码,这两个变量就是字符串securepassword和mysecretkey
- 删除不必要的__main函数
还原后结果:
C
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int checkpass(char* Str)
{
size_t length; // eax
size_t v3; // [esp+3Ch] [ebp-Ch]
// 补全缺失的变量(aSecurepassword, aMysecretkey)
const char* aMysecretkey = "mysecretkey";
const char* aSecurepassword = "securepassword";
if (strlen(Str) >= 6 && strlen(Str) <= 20) // 0x14 = 20
{
v3 = 0;
for (length = strlen("securepassword"); v3 < length; ++v3 ) // 显然i为length, 并将++v3上移
{
if (((unsigned __int8)aMysecretkey[v3 % strlen("mysecretkey")] ^ (unsigned __int8)Str[v3]) != aSecurepassword[v3])
{
puts("Incorrect password.");
return 0;
}
}
return 1;
}
else
{
printf("Password length must be between %d and %d characters.\n", 6, 20);
return 0;
}
}
int __cdecl main(int argc, const char** argv, const char** envp)
{
char Str[100]; // [esp+1Ch] [ebp-64h] BYREF
// 删除不必要的__main函数
printf("Enter your password: ");
scanf("%99s", Str);
checkpass(Str);
return 0;
}
那么显然该程序首先判断输入的passkey是否在6和20之间,随后逐字节将输入的passkey与aMysecretkey变量异或,并判断是否与aSecurepassword变量相等,由于异或的特性,存在a^b^b = a,假设a^b = c,那么如果我们已知b和c,想要得到a,只需要计算b^c即可,带入代码可得:
Text Only
由于passkey ^ aMysecretkey ^ aMysecretkey = passkey
且passkey ^ aMysecretkey = aSecurepassword
所以aSecurepassword ^ aMysecretkey = passkey
解密代码如下:
Python
def main():
aSecurepassword = "securepassword"
aMysecretkey = "mysecretkey"
# calculate xor of two strings
passkey = ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(aSecurepassword,
aMysecretkey))
print("XOR Result:", passkey)
if __name__ == "__main__":
main()

方法二(修改程序判断逻辑)¶
AES版本¶
上文我们练习了异或算法,这次我们练习更常见的AES算法