我正在使用内联汇编来构建一组密码,我将使用这些密码对给定散列进行强力操作。我用这个website作为构建密码的参考。使用内联汇编和访问c变量的多线程
这是在单线程环境中工作完美无缺。它会产生无限量的递增密码。
因为我只有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个线程运行该程序,并在打印的明文权的汇编指令后的内容,产生:
b
b
d
d
f
f
...
EDIT2:
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;
}
如果两个或多个线程可以访问它们,您需要锁定对“明文”和“charsetTable”变量的访问。从你发布的内容中很难判断,这是否真的是问题所在。你能告诉我们线程代码吗? –
您应该真正将'asm'声明为'volatile',否则GCC可能会将其移动。另外,你应该在clobberlist中有“内存”。见[here](http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3)。 – user786653
尽量避免全局变量。在这种情况下,简单的方法是使用堆栈变量。另一种更复杂的可能性是使用线程局部变量。 – hirschhornsalz