我正在使用內聯彙編來構建一組密碼,我將使用這些密碼對給定散列進行強力操作。我用這個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