2015-04-15 6 views
5

* ein weiteres Update in Code und Fragen *Brute-Force in OpenCL (Hafen von CUDA) funktioniert nicht

gerade begonnen OpenCL etwa 1 Woche oder so, und ich versuchte, in dem Hafen ein CUDA-Programm über bruteforcing zu lernen ein MD5-Hash, um eine tatsächliche Zeichenfolge daraus zu erhalten. Ich benutze 2 Dateien: kernel.cl und main.cpp.

//this is kernel.cl 

{...*defining some md5 variables*...} 

void IncrementBruteGPU(unsigned char* ourBrute, unsigned int charSetLen, unsigned int bruteLength, unsigned int incrementBy){ 
int i = 0; 
while(incrementBy > 0 && i < bruteLength) 
{ 
    int add = incrementBy + ourBrute[i]; 
    ourBrute[i] = add % charSetLen; 
    incrementBy = add/charSetLen; 
    i++; 
}} 

void md5_vfy(unsigned char* data, unsigned int length, unsigned int *a1, unsigned int *b1, unsigned int *c1, unsigned int *d1){ 
{...*some md5 hashing function*...}} 

__kernel void crack(unsigned int numThreads, unsigned int charSetLen, 
       unsigned int bruteLength, unsigned int v1, 
       unsigned int v2, unsigned int v3, unsigned int v4, 
       __constant unsigned char *cudaBrute, 
       __constant unsigned char *cudaCharSet, 
       __global unsigned char *correctPass){ 
//count index 
unsigned int idx = get_global_id(0); 
int totalLen = 0; 
int bruteStart = 0; 

unsigned char word[14]; 
unsigned char ourBrute[14]; 

int i = 0; 

for(i = 0; i < 14; i++) 
{ 
    ourBrute[i] = cudaBrute[i]; 
} 

i = 0; 
bruteStart = i; 
i+= bruteLength; 
totalLen = i; 

IncrementBruteGPU(ourBrute, charSetLen, bruteLength, idx); 
int timer = 0; 
for(timer = 0; timer < 200; timer++) 
{ 
    //substitute into string 
    for(i = 0; i < bruteLength; i++) 
    { 
     word[i+bruteStart] = cudaCharSet[ourBrute[i]]; 
    } 

    unsigned int c1 = 0, c2 = 0, c3 = 0, c4 = 0; 
    //find MD5 hash from word 
    md5_vfy(word,totalLen, &c1, &c2, &c3, &c4); 

    //compare hash with the input one 
    if(c1 == v1 && c2 == v2 && c3 == v3 && c4 == v4) 
    { 
     //place the right string into first index of array 
     int j; 
     for(j= 0; j < 14; j++) 
     { 
      correctPass[j] = word[j]; 
     } 
     correctPass[totalLen] = 0; 
    } 
    IncrementBruteGPU(ourBrute, charSetLen, bruteLength, numThreads); 
}} 

und dies ist der Haupt:

//just the main, not the entire main.cpp 
int main(int argc, char** argv){ 
int digit=1; 
int charSetLen = 0; 
char hash[32]; 
char *strhash[32]; 

printf("Insert Hash: "); 
scanf("%s", strhash); 
system("cls"); 

int numThreads = BLOCKS * THREADS_PER_BLOCK; 

unsigned char currentBrute[14]; 
unsigned char cpuCorrectPass[14]; 

ZeroFill(currentBrute, 14); 
ZeroFill(cpuCorrectPass, 14); 

charSetLen = 65; 
unsigned char charSet[65]; 
memcpy(charSet, " [email protected]_", charSetLen); 
memcpy(hash, strhash, 32); 

//break hash into 4 processes of MD5 
unsigned int v1, v2, v3, v4; 
md5_to_ints(hash,&v1,&v2,&v3,&v4); 

//openCL starts here 
cl_platform_id cpPlatform;  // OpenCL platform 
cl_device_id device_id;   // device ID 
cl_context context;    // context 
cl_command_queue queue;   // command queue 
cl_program program;    // program 
cl_kernel kernel;     // kernel 

cl_int err; 
cl_mem correctPass; 
cl_mem cudaCharSet; 
cl_mem cudaBrute; 

size_t globalSize, localSize; 
size_t bytes = 14*sizeof(char); 

//5 work-groups 
localSize = 10; 
globalSize = 50; 

// Bind to platform 
err = clGetPlatformIDs(1, &cpPlatform, NULL); 
if(err < 0) { 
    perror("Couldn't identify a platform"); 
    exit(1); 
} 

// Get ID for the device 
err = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL); 
if(err == CL_DEVICE_NOT_FOUND) { 
    err = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_CPU, 1, &device_id, NULL); 
} 
if(err < 0) { 
    perror("Couldn't access any devices"); 
    exit(1); 
} 

// Create a context 
context = clCreateContext(0, 1, &device_id, NULL, NULL, &err); 
if(err < 0) { 
    perror("Couldn't create a context"); 
    exit(1); 
} 

// Create a command queue 
queue = clCreateCommandQueue(context, device_id, CL_QUEUE_PROFILING_ENABLE, &err); 
if(err < 0) { 
    perror("Couldn't create a command queue"); 
    exit(1); 
} 

// Build the program executable 
program = build_program(context, device_id, PROGRAM_FILE); 

// Create the compute kernel in the program we wish to run 
kernel = clCreateKernel(program, KERNEL_FUNC, &err); 
if(err < 0) { 
    perror("Couldn't create a kernel"); 
    exit(1); 
} 

// Create the input and output arrays in device memory for our calculation 
cudaBrute = clCreateBuffer(context, CL_MEM_READ_ONLY, 14, NULL, NULL); 
cudaCharSet = clCreateBuffer(context, CL_MEM_READ_ONLY, 95, NULL, NULL); 
correctPass = clCreateBuffer(context, CL_MEM_READ_WRITE, 14, NULL, NULL); 

// Write our data set into the input array in device memory 
err = clEnqueueWriteBuffer(queue, correctPass, CL_TRUE, 0, 
    bytes, cpuCorrectPass, 0, NULL, NULL); 
err = clEnqueueWriteBuffer(queue, cudaCharSet, CL_TRUE, 0, 
    bytes, charSet, 0, NULL, NULL); 

// Set the arguments to our compute kernel 
err = clSetKernelArg(kernel, 0, sizeof(unsigned int), &numThreads); 
err |= clSetKernelArg(kernel, 1, sizeof(unsigned int), &charSetLen); 
err |= clSetKernelArg(kernel, 2, sizeof(unsigned int), &digit); 
err |= clSetKernelArg(kernel, 3, sizeof(unsigned int), &v1); 
err |= clSetKernelArg(kernel, 4, sizeof(unsigned int), &v2); 
err |= clSetKernelArg(kernel, 5, sizeof(unsigned int), &v3); 
err |= clSetKernelArg(kernel, 6, sizeof(unsigned int), &v4); 
err |= clSetKernelArg(kernel, 7, sizeof(cl_mem), &cudaBrute); 
err |= clSetKernelArg(kernel, 8, sizeof(cl_mem), &cudaCharSet); 
err |= clSetKernelArg(kernel, 9, sizeof(cl_mem), &correctPass); 

bool finished = false; 
int ct = 0; 
while(true){ 
do{ 
    err = clEnqueueWriteBuffer(queue, cudaBrute, CL_TRUE, 0, 
     bytes, currentBrute, 0, NULL, NULL); 

// Execute the kernel over the entire range of the data set 
    err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalSize, &localSize, 
                  0, NULL, NULL); 

// Wait for the command queue to get serviced before reading back results 
    clFinish(queue); 

// Read the results from the device 
    clEnqueueReadBuffer(queue, correctPass, CL_TRUE, 0, bytes, cpuCorrectPass, 0, NULL, NULL); 

    if(cpuCorrectPass[0] != 0) 
    {  
     printf("MD5 Cracked---->\t"); 
     int k = 0; 
     while(cpuCorrectPass[k] != 0) 
     { 
      printf("%c", cpuCorrectPass[k]); 
      k++; 
     } 
     printf("\n\n"); 
     return 0; 
    } 
    finished = BruteIncrement(currentBrute, charSetLen, digit, numThreads * 200); 
    if(ct % OUTPUT_INTERVAL == 0) 
    { 
     printf("STATUS: "); 
     int k = 0; 
     for(k = 0; k < digit; k++) 
      printf("%c",charSet[currentBrute[k]]); 
     printf("\n"); 
    } 
    ct++; 
} while(!finished); 
    digit=digit+1; 
} 
// release OpenCL resources 
clReleaseMemObject(correctPass); 
clReleaseMemObject(cudaCharSet); 
clReleaseMemObject(cudaBrute); 
clReleaseProgram(program); 
clReleaseKernel(kernel); 
clReleaseCommandQueue(queue); 
clReleaseContext(context); 

return 0;} 

das Problem mit diesem Programm ist es findet nie die richtige Zeichenfolge. Scheint wie die Idee von Brute-Hashes zu vergleichen und der Eingabe-Hash funktioniert nicht. Ich habe die CUDA-Version perfekt funktioniert.

Bitte sagen Sie mir, was das nicht richtig funktioniert. Ich vermute, entweder der Kernel funktioniert überhaupt nicht oder mein Mangel an Verständnis über Lese/Schreib-Speicher & Puffer in openCL oder im Allgemeinen verursachen dies.

* Wenn Sie alle Dateien sehen möchten, bitte fragen Sie mich., Weil ich denke, es wird zu lange dauern, wenn ich sie hier poste. danke vorher und sorry für die schlechte Formatierung.

+0

Sind Sie die Rückgabecodes von den OpenCL API-Aufrufe Kontrolle (dh der Wert von 'err' nach API Anruf)? – jprice

+0

@jprice Ich habe das überprüft, habe ein Fehler-Feedback beim Erstellen des Kernels bekommen und das behoben. Jetzt befinden sich die Probleme in der Datei kernel.cl. zufällig, wussten Sie, wie Sie diese Variablen korrekt in openCL benutzerdefinierte Header-Datei definieren? '__global __constant unsigned char cudaBrute [MAX_BRUTE_LENGTH]; __global __konstante unsigned char cudaCharSet [95]; __global unsigned char correctPass [MAX_TOTAL]; ' – alfonsouchiha

+0

Sie müssen Ihre OpenCL-Puffer als Argumente an den Kernel übergeben, die als (zum Beispiel) 'global uchar * data' deklariert sind. – jprice

Antwort

2

Ihr Kernel liest und schreibt aus konstanten Arrays, die im Programmbereich des OpenCL-Kernel-Quellcodes definiert sind (cudaBrute, cudaCharSet, correctPass). Diese Arrays werden nicht initialisiert, und der Host wird niemals die Ausgabe vom Kernel erhalten. Um Eingabedaten vom Host an einen Kernel zu übertragen und Ergebnisse von einem Kernel abzurufen, müssen Sie Kernel-Argumente und keine Programmbereichsvariablen verwenden.

Ihre Kernel-Definition sollte wie folgt aussehen:

__kernel void crack(unsigned int numThreads, unsigned int charSetLen, 
        unsigned int bruteLength, unsigned int v1, 
        unsigned int v2, unsigned int v3, unsigned int v4, 
        __global uchar *cudaBrute, 
        __global uchar *cudaCharSet, 
        __global uchar *correctPass) 
{ 
    ... 
    (do stuff with the arguments) 
    ... 
} 

Um die Argumente von Ihrem Host-Code festgelegt, würden Sie so etwas tun:

// Set the arguments to our compute kernel 
err = clSetKernelArg(kernel, 0, sizeof(int), &numThreads); 
err |= clSetKernelArg(kernel, 1, sizeof(int), &charSetLen); 
err |= clSetKernelArg(kernel, 2, sizeof(int), &digit); 
err |= clSetKernelArg(kernel, 3, sizeof(unsigned int), &v1); 
err |= clSetKernelArg(kernel, 4, sizeof(unsigned int), &v2); 
err |= clSetKernelArg(kernel, 5, sizeof(unsigned int), &v3); 
err |= clSetKernelArg(kernel, 6, sizeof(unsigned int), &v4); 
err |= clSetKernelArg(kernel, 7, sizeof(cl_mem), &cudaBrute); 
err |= clSetKernelArg(kernel, 8, sizeof(cl_mem), &cudaCharSet); 
err |= clSetKernelArg(kernel, 9, sizeof(cl_mem), &correctPass); 

Hinweis das zweite Argument, das ist der Argument-Index in Ihrer Kernel-Definition und wie für die letzten drei Argumente, die wir jetzt übergeben, in dem Puffer, den wir mit clCreateBuffer erstellt haben.


(EDIT: Noch ein paar Fragen nach der weiteren Fehlersuche gefunden wurden)

Sie aktualisieren den Wert von digit auf dem Host. Um diesen aktualisierten Wert für jeden Kernelaufruf an das Gerät zu übergeben, müssen Sie das Kernelargument neu setzen. Sie können, indem Sie diese Zeile dies einfach tun, um kurz vor Ihrem clEnqueueNDRangeKernel Anruf:

err |= clSetKernelArg(kernel, 2, sizeof(unsigned int), &digit); 

Wenn Sie Daten auf den cudaCharSet Puffer zu schreiben, müssen Sie sicherstellen, dass Sie die richtige Menge schreiben. Ihr Code verwendet derzeit bytes (die 14), aber das ist wirklich charSetLen sein sollte (was 65):

err = clEnqueueWriteBuffer(queue, cudaCharSet, CL_TRUE, 0, 
          charSetLen, charSet, 0, NULL, NULL); 
+0

endlich macht es Sinn für mich über den vorbeifahrenden Puffer, danke. Aber noch, es löst diese 2 Probleme nicht, habe die Ursachen nicht gefunden ... Was ist das Äquivalent von 'dim3 dimGrid (64); dim3 dimBlock (128); 'in openCL? – alfonsouchiha

+0

@alfonsouchiha Lokale Größe = '128', globale Größe =' 128 * 64' – jprice

+0

Muss ich jede Variable im Kernel in '_global' oder '_constant' schreiben, z. '_kernel void crack (_global int numThreads, _globale int Ziffer, .....) {...}'? – alfonsouchiha

Verwandte Themen