【发布时间】:2011-09-18 14:11:23
【问题描述】:
我正在使用内联汇编来构造一组密码,我将使用这些密码来暴力破解给定的哈希值。我用这个website 作为密码构造的参考。
这在单线程环境中完美运行。它会产生无限数量的递增密码。
因为我只有基本的 asm 知识,所以我理解这个想法。 gcc使用ATT,所以我用-masm=intel编译
在尝试对程序进行多线程处理时,我意识到这种方法可能行不通。
以下代码使用 2 个全局 C 变量,我假设这可能是问题所在。
__asm__("pushad\n\t"
"mov edi, offset plaintext\n\t" <---- global variable
"mov ebx, offset charsetTable\n\t" <---- again
"L1: movzx eax, byte ptr [edi]\n\t"
" movzx eax, byte ptr [charsetTable+eax]\n\t"
" cmp al, 0\n\t"
" je L2\n\t"
" mov [edi],al\n\t"
" jmp L3\n\t"
"L2: xlat\n\t"
" mov [edi],al\n\t"
" inc edi\n\t"
" jmp L1\n\t"
"L3: popad\n\t");
它在明文变量中产生一个不确定的结果。
如何创建一个解决方法,让每个线程都访问自己的明文变量? (如果这是问题......)。
我尝试修改此代码以使用扩展程序集,但每次都失败了。可能是因为所有教程都使用 ATT 语法。
我真的很感激任何帮助,因为我现在被困了几个小时:(
编辑:使用 2 个线程运行程序,并在 asm 指令之后打印明文内容,生成:bb
@987654327 @dff
...
编辑2:
pthread_create(&thread[i], NULL, crack, (void *) &args[i]))
[...]
void *crack(void *arg) {
struct threadArgs *param = arg;
struct crypt_data crypt; // storage for reentrant version of crypt(3)
char *tmpHash = NULL;
size_t len = strlen(param->methodAndSalt);
size_t cipherlen = strlen(param->cipher);
crypt.initialized = 0;
for(int i = 0; i <= LIMIT; i++) {
// intel syntax
__asm__ ("pushad\n\t"
//mov edi, offset %0\n\t"
"mov edi, offset plaintext\n\t"
"mov ebx, offset charsetTable\n\t"
"L1: movzx eax, byte ptr [edi]\n\t"
" movzx eax, byte ptr [charsetTable+eax]\n\t"
" cmp al, 0\n\t"
" je L2\n\t"
" mov [edi],al\n\t"
" jmp L3\n\t"
"L2: xlat\n\t"
" mov [edi],al\n\t"
" inc edi\n\t"
" jmp L1\n\t"
"L3: popad\n\t");
tmpHash = crypt_r(plaintext, param->methodAndSalt, &crypt);
if(0 == memcmp(tmpHash+len, param->cipher, cipherlen)) {
printf("success: %s\n", plaintext);
break;
}
}
return 0;
}
【问题讨论】:
-
如果两个或多个线程可以访问它们,您需要锁定对
plaintext和charsetTable变量的访问。从您发布的内容很难判断这是否真的是问题所在。你能告诉我们线程代码吗? -
你真的应该将你的
asm声明为volatile,否则 GCC 可能会移动它。此外,您应该在clobberlist 中有memory。见here。 -
尽量避免使用全局变量。在这种情况下,简单的方法是使用堆栈变量。另一种更复杂的可能性是使用线程局部变量。
-
顺便说一句,asm 代码很慢。特别是应该避免使用
xlat指令(这可能是 20 年前最快的方式)。
标签: c multithreading assembly x86 brute-force