2 * Copyright (C) 2009 by David Kedves <kedazo@gmail.com>
4 * This file is part of rarcrack.
6 * Rarcrack is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Rarcrack is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with rarcrack. If not, see <http://www.gnu.org/licenses/>.
23 /* TODO: on crack i need to use system() call, it's working on win/linux/macosx...
30 int main(int argc, char** argv) {
32 int ret = system("7z t -y -p10f0 test.7z");
33 printf("Return: %d\n", ret);
40 char* ABC = (char*) &default_ABC;
43 char password[PWD_LEN+1] = {'\0','\0'}; //this contains the actual password
44 char password_good[PWD_LEN+1] = {'\0', '\0'}; //this changed only once, when we found the good passord
45 unsigned int curr_len = 1; //current password length
46 long counter = 0; //this couning probed passwords
47 xmlMutexPtr pwdMutex; //mutex for password char array
48 char filename[255]; //the archive file name
49 char statname[259]; //status xml file name filename + ".xml"
52 xmlMutexPtr finishedMutex;
53 char finalcmd[300] = {'\0', '\0'}; //this depending on arhive file type, it's a command to test file with password
55 char * getfirstpassword() {
62 inline void savestatus() {
63 xmlNodePtr root = NULL;
64 xmlNodePtr node = NULL;
66 if ((strlen(statname) > 0) && (status != NULL)) {
67 root = xmlDocGetRootElement(status);
69 xmlMutexLock(finishedMutex);
70 for (node = root->children; node; node = node->next) {
71 if (xmlStrcmp(node->name, "current") == 0) {
72 xmlMutexLock(pwdMutex);
73 tmp = xmlEncodeEntitiesReentrant(status, (const xmlChar*) &password);
74 xmlMutexUnlock(pwdMutex);
76 if (password[0] == '\0')
77 xmlNodeSetContent(node->children, getfirstpassword());
79 xmlNodeSetContent(node->children, tmp);
82 } else if ((finished == 1) && (xmlStrcmp(node->name,"good_password") == 0)) {
83 tmp = xmlEncodeEntitiesReentrant(status, (const xmlChar*) &password_good);
85 xmlNodeSetContent(node->children, tmp);
89 xmlMutexUnlock(finishedMutex);
91 xmlSaveFormatFileEnc(statname, status, "UTF-8", 1);
96 inline int abcnumb(char a) {
98 for (i = 0; i<ABCLEN; i++)
99 if (ABC[i] == a) return i;
104 xmlNodePtr root = NULL;
105 xmlNodePtr node = NULL;
106 xmlParserCtxtPtr parserctxt;
110 totest = fopen(statname, "r");
111 if (totest != NULL) {
113 status = xmlParseFile(statname);
116 root = xmlDocGetRootElement(status);
118 status = xmlNewDoc(NULL);
120 parserctxt = xmlNewParserCtxt();
121 for (node = root->children; node; node = node->next) {
122 if (xmlStrcmp(node->name, "abc") == 0) {
123 if (node->children && (strlen(node->children->content) > 0)) {
124 ABC = xmlStringDecodeEntities(parserctxt,
125 node->children->content,XML_SUBSTITUTE_BOTH,0,0,0);
128 } else if (xmlStrcmp(node->name, "current") == 0) {
129 if (node->children && (strlen(node->children->content) > 0)) {
130 tmp = xmlStringDecodeEntities(parserctxt,
131 node->children->content,XML_SUBSTITUTE_BOTH,0,0,0);
132 strcpy(password,tmp);
133 curr_len = strlen(password);
134 printf("INFO: Resuming cracking from password: '%s'\n",password);
138 } else if (xmlStrcmp(node->name, "good_password") == 0) {
139 if (node->children && (strlen(node->children->content) > 0)) {
140 tmp = xmlStringDecodeEntities(parserctxt,
141 node->children->content,XML_SUBSTITUTE_BOTH,0,0,0);
142 strcpy(password,tmp);
143 curr_len = strlen(password);
144 xmlMutexLock(finishedMutex);
146 xmlMutexUnlock(finishedMutex);
147 strcpy((char*) &password_good, (char*) &password);
148 printf("GOOD: This archive was succesfully cracked\n");
149 printf(" The good password is: '%s'\n", password);
155 xmlFreeParserCtxt(parserctxt);
157 root = xmlNewNode(NULL, "rarcrack");
158 xmlDocSetRootElement(status, root);
159 node = xmlNewTextChild(root, NULL, "abc", ABC);
160 node = xmlNewTextChild(root, NULL, "current", getfirstpassword());
161 node = xmlNewTextChild(root, NULL, "good_password", "");
167 void nextpass2(char* p, unsigned int n) {
169 if (p[n] == ABC[ABCLEN-1]) {
174 for (i=curr_len; i>=0; i--)
181 p[n] = ABC[abcnumb(p[n])+1];
185 inline char* nextpass() { //IMPORTANT: the returned string must be freed
186 char *ok = malloc(sizeof(char)*(PWD_LEN+1));
187 xmlMutexLock(pwdMutex);
188 strcpy(ok, password);
189 nextpass2((char*) &password, curr_len - 1);
190 xmlMutexUnlock(pwdMutex);
194 void * status_thread() {
196 const short status_sleep = 3;
198 xmlMutexLock(finishedMutex);
199 pwds = counter / status_sleep;
201 xmlMutexUnlock(finishedMutex);
202 xmlMutexLock(pwdMutex);
203 printf("Probing: '%s' [%d pwds/sec]\n", password, pwds);
204 xmlMutexUnlock(pwdMutex);
210 void * crack_thread() {
216 current = nextpass();
217 sprintf((char*)&cmd, finalcmd, current, filename);
218 Pipe = popen(cmd, "r");
219 while (!feof(Pipe)) {
220 fgets((char*)&ret, 200, Pipe);
221 if (strcasestr(ret, "ok") != NULL) {
222 strcpy(password_good, current);
223 xmlMutexLock(finishedMutex);
225 printf("GOOD: password cracked: '%s'\n", current);
226 xmlMutexUnlock(finishedMutex);
232 xmlMutexLock(finishedMutex);
235 xmlMutexUnlock(finishedMutex);
238 xmlMutexUnlock(finishedMutex);
243 void crack_start(unsigned int threads) {
246 for (i = 0; i < threads; i++) {
247 (void) pthread_create(&th[i], NULL, crack_thread, NULL);
249 (void) pthread_create(&th[12], NULL, stats_thread, NULL);
250 for (i = 0; i < threads; i++) {
251 (void) pthread_join(th[i], NULL);
253 (void) pthread_join(th[12], NULL);
257 void init(int argc, char **argv) {
261 int archive_type = -1;
265 pwdMutex = xmlNewMutex();
266 finishedMutex = xmlNewMutex();
268 printf("USAGE: rarcrack encrypted_archive.ext [--threads NUM] [--type rar|zip|7z]\n");
269 printf(" For more information please run \"rarcrack --help\"\n");
272 for (i = 1; i < argc; i++) {
273 if (strcmp(argv[i],"--help") == 0) {
274 printf("Usage: rarcrack encrypted_archive.ext [--threads NUM] [--type rar|zip|7z]\n\n");
275 printf("Options: --help: show this screen.\n");
276 printf(" --type: you can specify the archive program, this needed when\n");
277 printf(" the program couldn't detect the proper file type\n");
278 printf(" --threads: you can specify how many threads\n");
279 printf(" will be run, maximum 12 (default: 2)\n\n");
280 printf("Info: This program supports only RAR, ZIP and 7Z encrypted archives.\n");
281 printf(" RarCrack! usually detects the archive type.\n\n");
284 } else if (strcmp(argv[i],"--threads") == 0) {
285 if ((i + 1) < argc) {
286 sscanf(argv[++i], "%d", &threads);
287 if (threads < 1) threads = 1;
289 printf("INFO: number of threads adjusted to 12\n");
293 printf("ERROR: missing parameter for option: --threads!\n");
296 } else if (strcmp(argv[i],"--type") == 0) {
297 if ((i + 1) < argc) {
298 sscanf(argv[++i], "%s", &test);
299 for (j = 0; strcmp(TYPE[j], "") != 0; j++) {
300 if (strcmp(TYPE[j], test) == 0) {
301 strcpy(finalcmd, CMD[j]);
306 if (archive_type < 0) {
307 printf("WARNING: invalid parameter --type %s!\n", argv[i]);
311 printf("ERROR: missing parameter for option: --type!\n");
315 strcpy((char*)&filename, argv[i]);
321 sprintf((char*)&statname,"%s.xml",(char*)&filename);
322 totest = fopen(filename,"r");
323 if (totest == NULL) {
324 printf("ERROR: The specified file (%s) is not exists or \n", filename);
325 printf(" you don't have a right permissions!\n");
329 if (finalcmd[0] == '\0') { //when we specify the file type, the programm will skip the test
330 sprintf((char*)&test, CMD_DETECT, filename);
331 totest = popen(test,"r");
332 fscanf(totest,"%s",(char*)&test);
334 for (i = 0; strcmp(MIME[i],"") != 0; i++) {
335 if (strcmp(MIME[i],test) == 0) {
336 strcpy(finalcmd,CMD[i]);
341 printf("INFO: detected file type: %s\n", TYPE[archive_type]);
343 printf("INFO: the specified archive type: %s\n", TYPE[archive_type]);
344 if (finalcmd[0] == '\0') {
345 printf("ERROR: Couldn't detect archive type\n");
348 printf("INFO: cracking %s, status file: %s\n", filename, statname);
349 if (loadstatus() == 1) {
350 printf("ERROR: The status file (%s) is corrupted!\n", statname);
353 ABCLEN = strlen(ABC);
354 if (password[0] == '\0')
355 password[0] = ABC[0];
356 crack_start(threads);