インライン アセンブリを使用して一連のパスワードを作成しています。これを使用して、特定のハッシュに対してブルート フォースを実行します。パスワードの作成にあたっては、 こちらのサイトを参考にさせていただきました。
これは、シングルスレッド環境で問題なく動作しています。無限に増加するパスワードを生成します。
私は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 命令の直後にプレーンテキストの内容を出力すると、次のようになり
b
b
d
d
f
f
ます。
編集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;
}