gpt4 book ai didi

c - 具有内联汇编和访问 c 变量的多线程

转载 作者:行者123 更新时间:2023-12-04 22:08:28 31 4
gpt4 key购买 nike

我正在使用内联汇编来构建一组密码,我将使用这些密码对给定的哈希值进行暴力破解。我用了这个 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指令后立即打印明文内容,产生:
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;
}

最佳答案

由于您已经在使用 pthreads,另一种选择是将由多个线程修改的变量变成每线程变量(线程特定数据)。参见 pthread_getspecific OpenGroup manpage .它的工作方式如下:

在主线程中(在创建其他线程之前),执行:

static pthread_key_y tsd_key;
(void)pthread_key_create(&tsd_key); /* unlikely to fail; handle if you want */

然后在每个线程中,使用 plaintext/charsetTable 变量(或更多类似变量),执行:

struct { char *plainText, char *charsetTable } *str =
pthread_getspecific(tsd_key);

if (str == NULL) {
str = malloc(2 * sizeof(char *));
str.plainText = malloc(size_of_plaintext);
str.charsetTable = malloc(size_of_charsetTable);
initialize(str.plainText); /* put the data for this thread in */
initialize(str.charsetTable); /* ditto */
pthread_setspecific(tsd_key, str);
}
char *plaintext = str.plainText;
char *charsetTable = str.charsetTable;

或者创建/使用多个键,每个这样的变量一个;在这种情况下,您不会获得 str 容器/双重间接/附加 malloc

带有 gcc 内联 asm 的英特尔汇编语法,嗯,不是很好;特别是,指定输入/输出操作数并不容易。我认为要使用 pthread_getspecific 机制,您需要更改代码以执行以下操作:

__asm__("pushad\n\t"
"push tsd_key\n\t" <---- threadspecific data key (arg to call)
"call pthread_getspecific\n\t" <---- gets "str" as per above
"add esp, 4\n\t" <---- get rid of the func argument
"mov edi, [eax]\n\t" <---- first ptr == "plainText"
"mov ebx, [eax + 4]\n\t" <---- 2nd ptr == "charsetTable"
...

这样一来,它就变成了无锁,代价是使用更多内存(每个线程一个纯文本/charsetTable),以及额外的函数调用(到pthread_getspecific())。此外,如果执行上述操作,请确保通过 pthread_atexit() free() 每个线程的特定数据,否则会泄漏。

如果您的函数执行速度很快,那么锁是一种更简单的解决方案,因为您不需要线程特定数据的所有设置/清理开销;如果函数运行缓慢或调用非常频繁,那么锁将成为瓶颈——在这种情况下,TSD 的内存/访问开销是合理的。您的里程可能会有所不同。

关于c - 具有内联汇编和访问 c 变量的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7462002/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com