Skip to content

Commit b69f72c

Browse files
author
knabberknusperhaus
committed
Update
1 parent 2fe20ef commit b69f72c

File tree

3 files changed

+80
-24
lines changed

3 files changed

+80
-24
lines changed

cpyrit/cpyrit.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222

2323
int numThreads = 4;
2424

25+
#ifdef HAVE_CUDA
26+
int cudadev;
27+
int cudadevcount;
28+
struct cudaDeviceProp cuda_devprop;
29+
#endif
30+
2531
#ifdef HAVE_PADLOCK
2632

2733
pthread_mutex_t padlock_sigmutex;
@@ -339,7 +345,16 @@ cpyrit_pmklist(PyObject *self, PyObject *args)
339345
}
340346

341347
#ifdef HAVE_CUDA
348+
//Will be linked as object file
342349
PyObject *cpyrit_cuda(PyObject *self, PyObject *args);
350+
351+
PyObject *cpyrit_devprops(PyObject *self, PyObject *args)
352+
{
353+
if (!PyArg_ParseTuple(args, "")) return NULL;
354+
355+
return Py_BuildValue("iisiiii", cudadevcount, cudadev, &cuda_devprop.name, cuda_devprop.totalGlobalMem,
356+
cuda_devprop.regsPerBlock, cuda_devprop.clockRate, cuda_devprop.multiProcessorCount);
357+
}
343358
#endif
344359

345360
static PyMethodDef SpamMethods[] = {
@@ -354,6 +369,7 @@ static PyMethodDef SpamMethods[] = {
354369

355370
#ifdef HAVE_CUDA
356371
{"calc_cuda", cpyrit_cuda, METH_VARARGS, "Calculate PMKs from ESSID and list of strings"},
372+
{"cudaprops", cpyrit_devprops, METH_VARARGS, "Returns a tuple with some properties about main device"},
357373
#endif
358374
{NULL, NULL, 0, NULL}
359375
};
@@ -362,25 +378,41 @@ PyMODINIT_FUNC
362378
init_cpyrit(void)
363379
{
364380
(void) Py_InitModule("_cpyrit", SpamMethods);
365-
}
366-
367-
int
368-
main(int argc, char *argv[])
369-
{
370-
/* Initialize the Python interpreter. Required. */
371-
Py_Initialize();
372381

373-
init_cpyrit();
374382

375383
#ifdef HAVE_CUDA
384+
385+
// This is a somewhat awkward way to initialize the GPU as a CUDA-context
386+
// is thread specific. There is no guarantee that the cuda functions above will be called
387+
// by the same thread which called this code. However we will not force that as at
388+
// some point in the future we need multi-gpu functionality anyway.
376389
char* buffer;
377-
cudaMallocHost( (void**) &buffer, 4 );
378-
cudaFreeHost( buffer );
390+
cudaMallocHost((void**) &buffer, 4);
391+
cudaFreeHost(buffer);
392+
393+
cudaGetDeviceCount(&cudadevcount);
394+
cudaGetDevice(&cudadev);
395+
cudaGetDeviceProperties(&cuda_devprop, cudadev);
396+
int ret = cudaGetLastError();
397+
if (ret != cudaSuccess)
398+
{
399+
PyErr_SetString(PyExc_SystemError, cudaGetErrorString(ret));
400+
return;
401+
}
402+
379403
#endif
380404

381405
#ifdef HAVE_PADLOCK
382406
pthread_mutex_init(&padlock_sigmutex, NULL);
383407
#endif
408+
}
409+
410+
int
411+
main(int argc, char *argv[])
412+
{
413+
Py_Initialize();
414+
415+
init_cpyrit();
384416

385417
return -1;
386418
}

cpyrit/cpyrit.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,53 @@
2424

2525
class CUDACore(object):
2626
name = "Nvidia CUDA"
27-
description = "Yeah"
27+
ctype = "GPU"
2828
def __init__(self):
2929
assert 'calc_cuda' in dir(_cpyrit)
30-
self.gpu_perf = (0, 0)
31-
self.cpu_perf = (0, 0)
30+
self.buffersize = 1024
31+
props = _cpyrit.cudaprops()
32+
self.devicename = props[2]
33+
self.devicemem = int(props[3] / 1024.0 / 1024.0)
34+
self.deviceclock = int(props[5] / 1024.0)
3235

3336
def solve(self, essid, password):
3437
assert isinstance(essid, str)
3538
if isinstance(password, str):
3639
return _cpyrit.calc_pmk(essid, password)
3740
assert isinstance(password, list)
3841

39-
return _cpyrit.calc_cuda(essid, password)
42+
# The kernel allows a max. execution time of 5 seconds per call (usually) so we have to
43+
# limit the input-buffer to some degree. However the size of the input-buffer is crucial
44+
# to overall performance. Therefor buffersize is to be calibrated somewhere near
45+
# it's maximum value allowed. Target is 3.0 seconds execution time.
46+
res = []
47+
i = 0
48+
while i < len(password):
49+
t = time.time()
50+
res.extend(_cpyrit.calc_cuda(essid, password[i:i+self.buffersize]))
51+
i += self.buffersize
52+
if len(password[i:i+self.buffersize]) > self.buffersize:
53+
self.buffersize = int(max(1024, min(10240, (2 * self.buffersize + (3.0 / (time.time() - t) * self.buffersize)) / 3)))
54+
return res
55+
4056

4157
class CPUCore(object):
4258
name = "Standard CPU"
43-
description = "Yeah!"
59+
ctype = "CPU"
4460
def __init__(self):
4561
assert 'calc_pmklist' in dir(_cpyrit)
4662

4763
def solve(self, essid, password):
4864
assert isinstance(essid, str)
4965
if isinstance(password, list):
50-
return _cpyrit.calc_pmklist(essid, password)
66+
# slicing gives better interactivity to signals as _cpyrit's functions won't listen to them
67+
res = []
68+
for pwslice in xrange(0, len(password), 1000):
69+
res.extend(_cpyrit.calc_pmklist(essid, password[pwslice:pwslice+1000]))
70+
return res
5171
elif isinstance(password, str):
5272
return _cpyrit.calc_pmk(essid, password)
73+
5374
else:
5475
raise TypeError, "Password parameter must be string or list"
5576

pyrit_cli.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def __init__(self):
3838
"core_name": None,
3939
"essid": None,
4040
"file": None,
41-
"ncpus": 1}
41+
"ncpus": None}
4242
self.pyrit_obj = None
4343

4444
def progressbar(self, idx, max_idx):
@@ -208,10 +208,15 @@ def batchprocess(self):
208208
cp = cpyrit.CPyrit(ncpus = self.options["ncpus"])
209209
if self.options["core_name"] is not None:
210210
core = cp.getCore(self.options["core_name"])
211-
print "Selected core '%s' (%i CPUs)" % (core.name, cp.ncpus)
211+
print "Selected core '%s'" % core.name,
212212
else:
213213
core = cp.getCore()
214-
print "Using default core '%s' (%i CPUs)" % (core.name, cp.ncpus)
214+
print "Using default core '%s'" % core.name,
215+
if core.ctype == 'GPU':
216+
print "(Device '%s')" % core.devicename
217+
else:
218+
print "(%i CPUs)" % cp.ncpus
219+
215220
comptime = 0
216221
rescount = 0
217222
essids = self.pyrit_obj.list_essids()
@@ -240,8 +245,6 @@ def batchprocess(self):
240245
print "%i PMKs to do." % len(passwords)
241246

242247
if len(passwords) > 0:
243-
#We slice the workunit to smaller parts since calc_pmklist won't return on KeyboardInterrupt
244-
#the overhead of slicing is minimal
245248
for pwslice in xrange(0,len(passwords), 15000):
246249
pwset = passwords[pwslice:pwslice+15000]
247250
t = time.time()
@@ -276,19 +279,19 @@ def benchmark(self):
276279
print "%i PMKs in %.2f seconds: %.2f PMKs/s" % (len(pws), t, len(pws) / t)
277280
md = md5.new()
278281
map(md.update, [x[1] for x in res])
279-
print "Result hash: %s" % md.hexdigest(), {True: "OK", False: "FAILED"}[md.hexdigest() == "ef747d123821851a9bd1d1e94ba048ac"]
282+
print "Result hash:", {True: "OK", False: "FAILED"}[md.hexdigest() == "ef747d123821851a9bd1d1e94ba048ac"]
280283
print ""
281284

282285
if 'Nvidia CUDA' in [x[0] for x in c.listCores()]:
283286
core = c.getCore('Nvidia CUDA')
284-
print "Testing GPU core '%s'..." % core.name
287+
print "Testing GPU core '%s' (Device '%s')" % (core.name, core.devicename)
285288
t = time.time()
286289
res = sorted(core.solve('foo', pws))
287290
t = time.time() - t
288291
print "%i PMKs in %.2f seconds: %.2f PMKs/s" % (len(pws), t, len(pws) / t)
289292
md = md5.new()
290293
map(md.update, [x[1] for x in res])
291-
print "Result hash: %s" % md.hexdigest(), {True: "OK", False: "FAILED"}[md.hexdigest() == "ef747d123821851a9bd1d1e94ba048ac"]
294+
print "Result hash:", {True: "OK", False: "FAILED"}[md.hexdigest() == "ef747d123821851a9bd1d1e94ba048ac"]
292295
print ""
293296

294297
if __name__ == "__main__":

0 commit comments

Comments
 (0)