2 * Copyright (C) 2007 by David Zoltan Kedves
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the
17 * Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 char* ABC
= (char*) &default_ABC
;
26 char password
[PWD_LEN
+1] = {'\0','\0'}; //this contains the actual password
27 char password_good
[PWD_LEN
+1] = {'\0', '\0'}; //this changed only once, when we found the good passord
28 unsigned int curr_len
= 1; //current password length
29 long counter
= 0; //this couning probed passwords
30 xmlMutexPtr pwdMutex
; //mutex for password char array
31 char filename
[255]; //the archive file name
32 char statname
[259]; //status xml file name filename + ".xml"
35 xmlMutexPtr finishedMutex
;
36 char finalcmd
[300] = {'\0', '\0'}; //this depending on arhive file type, it's a command to test file with password
38 char * getfirstpassword() {
45 inline void savestatus() {
46 xmlNodePtr root
= NULL
;
47 xmlNodePtr node
= NULL
;
49 if ((strlen(statname
) > 0) && (status
!= NULL
)) {
50 root
= xmlDocGetRootElement(status
);
52 xmlMutexLock(finishedMutex
);
53 for (node
= root
->children
; node
; node
= node
->next
) {
54 if (xmlStrcmp(node
->name
, "current") == 0) {
55 xmlMutexLock(pwdMutex
);
56 tmp
= xmlEncodeEntitiesReentrant(status
, (const xmlChar
*) &password
);
57 xmlMutexUnlock(pwdMutex
);
59 if (password
[0] == '\0')
60 xmlNodeSetContent(node
->children
, getfirstpassword());
62 xmlNodeSetContent(node
->children
, tmp
);
65 } else if ((finished
== 1) && (xmlStrcmp(node
->name
,"good_password") == 0)) {
66 tmp
= xmlEncodeEntitiesReentrant(status
, (const xmlChar
*) &password_good
);
68 xmlNodeSetContent(node
->children
, tmp
);
72 xmlMutexUnlock(finishedMutex
);
74 xmlSaveFormatFileEnc(statname
, status
, "UTF-8", 1);
79 inline int abcnumb(char a
) {
81 for (i
= 0; i
<ABCLEN
; i
++)
82 if (ABC
[i
] == a
) return i
;
87 xmlNodePtr root
= NULL
;
88 xmlNodePtr node
= NULL
;
89 xmlParserCtxtPtr parserctxt
;
93 totest
= fopen(statname
, "r");
96 status
= xmlParseFile(statname
);
99 root
= xmlDocGetRootElement(status
);
101 status
= xmlNewDoc(NULL
);
103 parserctxt
= xmlNewParserCtxt();
104 for (node
= root
->children
; node
; node
= node
->next
) {
105 if (xmlStrcmp(node
->name
, "abc") == 0) {
106 if (node
->children
&& (strlen(node
->children
->content
) > 0)) {
107 ABC
= xmlStringDecodeEntities(parserctxt
,
108 node
->children
->content
,XML_SUBSTITUTE_BOTH
,0,0,0);
111 } else if (xmlStrcmp(node
->name
, "current") == 0) {
112 if (node
->children
&& (strlen(node
->children
->content
) > 0)) {
113 tmp
= xmlStringDecodeEntities(parserctxt
,
114 node
->children
->content
,XML_SUBSTITUTE_BOTH
,0,0,0);
115 strcpy(password
,tmp
);
116 curr_len
= strlen(password
);
117 printf("INFO: Resuming cracking from password: '%s'\n",password
);
121 } else if (xmlStrcmp(node
->name
, "good_password") == 0) {
122 if (node
->children
&& (strlen(node
->children
->content
) > 0)) {
123 tmp
= xmlStringDecodeEntities(parserctxt
,
124 node
->children
->content
,XML_SUBSTITUTE_BOTH
,0,0,0);
125 strcpy(password
,tmp
);
126 curr_len
= strlen(password
);
127 xmlMutexLock(finishedMutex
);
129 xmlMutexUnlock(finishedMutex
);
130 strcpy((char*) &password_good
, (char*) &password
);
131 printf("GOOD: This archive was succesfully cracked\n");
132 printf(" The good password is: '%s'\n", password
);
138 xmlFreeParserCtxt(parserctxt
);
140 root
= xmlNewNode(NULL
, "rarcrack");
141 xmlDocSetRootElement(status
, root
);
142 node
= xmlNewTextChild(root
, NULL
, "abc", ABC
);
143 node
= xmlNewTextChild(root
, NULL
, "current", getfirstpassword());
144 node
= xmlNewTextChild(root
, NULL
, "good_password", "");
150 void nextpass2(char* p
, unsigned int n
) {
152 if (p
[n
] == ABC
[ABCLEN
-1]) {
157 for (i
=curr_len
; i
>=0; i
--)
164 p
[n
] = ABC
[abcnumb(p
[n
])+1];
168 inline char* nextpass() { //IMPORTANT: the returned string must be freed
169 char *ok
= malloc(sizeof(char)*(PWD_LEN
+1));
170 xmlMutexLock(pwdMutex
);
171 strcpy(ok
, password
);
172 nextpass2((char*) &password
, curr_len
- 1);
173 xmlMutexUnlock(pwdMutex
);
177 void * status_thread() {
179 const short status_sleep
= 3;
182 xmlMutexLock(finishedMutex
);
183 pwds
= counter
/ status_sleep
;
187 xmlMutexUnlock(finishedMutex
);
188 xmlMutexLock(pwdMutex
);
189 printf("Probing: '%s' [%d pwds/sec]\n", password
, pwds
);
190 xmlMutexUnlock(pwdMutex
);
191 savestatus(); //FIXME: this is wrong, when probing current password(s) is(are) not finished yet, and the program is exiting
195 void * crack_thread() {
201 current
= nextpass();
202 sprintf((char*)&cmd
, finalcmd
, current
, filename
);
203 Pipe
= popen(cmd
, "r");
204 while (!feof(Pipe
)) {
205 fgets((char*)&ret
, 200, Pipe
);
206 if (strcasestr(ret
, "ok") != NULL
) {
207 strcpy(password_good
, current
);
208 xmlMutexLock(finishedMutex
);
210 printf("GOOD: password cracked: '%s'\n", current
);
211 xmlMutexUnlock(finishedMutex
);
217 xmlMutexLock(finishedMutex
);
220 xmlMutexUnlock(finishedMutex
);
223 xmlMutexUnlock(finishedMutex
);
228 void crack_start(unsigned int threads
) {
231 for (i
= 0; i
< threads
; i
++) {
232 (void) pthread_create(&th
[i
], NULL
, crack_thread
, NULL
);
234 (void) pthread_create(&th
[12], NULL
, status_thread
, NULL
);
235 for (i
= 0; i
< threads
; i
++) {
236 (void) pthread_join(th
[i
], NULL
);
238 (void) pthread_join(th
[12], NULL
);
242 void init(int argc
, char **argv
) {
246 int archive_type
= -1;
250 pwdMutex
= xmlNewMutex();
251 finishedMutex
= xmlNewMutex();
253 printf("USAGE: rarcrack encrypted_archive.ext [--threads NUM] [--type rar|zip|7z]\n");
254 printf(" For more information please run \"rarcrack --help\"\n");
257 for (i
= 1; i
< argc
; i
++) {
258 if (strcmp(argv
[i
],"--help") == 0) {
259 printf("Usage: rarcrack encrypted_archive.ext [--threads NUM] [--type rar|zip|7z]\n\n");
260 printf("Options: --help: show this screen.\n");
261 printf(" --type: you can specify the archive program, this needed when\n");
262 printf(" the program couldn't detect the proper file type\n");
263 printf(" --threads: you can specify how many threads\n");
264 printf(" will be run, maximum 12 (default: 2)\n\n");
265 printf("Info: This program supports only RAR, ZIP and 7Z encrypted archives.\n");
266 printf(" RarCrack! usually detects the archive type.\n\n");
269 } else if (strcmp(argv
[i
],"--threads") == 0) {
270 if ((i
+ 1) < argc
) {
271 sscanf(argv
[++i
], "%d", &threads
);
272 if (threads
< 1) threads
= 1;
274 printf("INFO: number of threads adjusted to 12\n");
278 printf("ERROR: missing parameter for option: --threads!\n");
281 } else if (strcmp(argv
[i
],"--type") == 0) {
282 if ((i
+ 1) < argc
) {
283 sscanf(argv
[++i
], "%s", &test
);
284 for (j
= 0; strcmp(TYPE
[j
], "") != 0; j
++) {
285 if (strcmp(TYPE
[j
], test
) == 0) {
286 strcpy(finalcmd
, CMD
[j
]);
291 if (archive_type
< 0) {
292 printf("WARNING: invalid parameter --type %s!\n", argv
[i
]);
296 printf("ERROR: missing parameter for option: --type!\n");
300 strcpy((char*)&filename
, argv
[i
]);
306 sprintf((char*)&statname
,"%s.xml",(char*)&filename
);
307 totest
= fopen(filename
,"r");
308 if (totest
== NULL
) {
309 printf("ERROR: The specified file (%s) is not exists or \n", filename
);
310 printf(" you don't have a right permissions!\n");
314 if (finalcmd
[0] == '\0') { //when we specify the file type, the programm will skip the test
315 sprintf((char*)&test
, CMD_DETECT
, filename
);
316 totest
= popen(test
,"r");
317 fscanf(totest
,"%s",(char*)&test
);
319 for (i
= 0; strcmp(MIME
[i
],"") != 0; i
++) {
320 if (strcmp(MIME
[i
],test
) == 0) {
321 strcpy(finalcmd
,CMD
[i
]);
326 printf("INFO: detected file type: %s\n", TYPE
[archive_type
]);
328 printf("INFO: the specified archive type: %s\n", TYPE
[archive_type
]);
329 if (finalcmd
[0] == '\0') {
330 printf("ERROR: Couldn't detect archive type\n");
333 printf("DEBUG: the unpack command is: '%s'\n", finalcmd);*/
334 printf("INFO: cracking %s, status file: %s\n", filename
, statname
);
335 if (loadstatus() == 1) {
336 printf("ERROR: The status file (%s) is corrupted!\n", statname
);
339 ABCLEN
= strlen(ABC
);
340 if (password
[0] == '\0')
341 password
[0] = ABC
[0];
342 crack_start(threads
);
346 int main(int argc
, char *argv
[]) {
347 printf("RarCrack! 0.2 by David Zoltan Kedves (kedazo@gmail.com)\n\n");
349 if (ABC
!= (char*) &default_ABC
)
353 xmlFreeMutex(pwdMutex
);
354 xmlFreeMutex(finishedMutex
);