modified: makefile
[GalaxyCodeBases.git] / c_cpp / etc / rarcrack / rarcrack.c
blob34f41e22c52fb50dd07f9d4b642d60d819ac997f
1 /*
2 * Copyright (C) 2007 by David Zoltan Kedves
3 * kedazo@gmail.com
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.
21 #include "rarcrack.h"
23 char* ABC = (char*) &default_ABC;
24 int ABCLEN;
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"
33 xmlDocPtr status;
34 int finished = 0;
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() {
39 static char ret[2];
40 ret[0] = ABC[0];
41 ret[1] = '\0';
42 return (char*) &ret;
45 inline void savestatus() {
46 xmlNodePtr root = NULL;
47 xmlNodePtr node = NULL;
48 xmlChar* tmp = NULL;
49 if ((strlen(statname) > 0) && (status != NULL)) {
50 root = xmlDocGetRootElement(status);
51 if (root) {
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);
58 if (node->children) {
59 if (password[0] == '\0')
60 xmlNodeSetContent(node->children, getfirstpassword());
61 else
62 xmlNodeSetContent(node->children, tmp);
64 xmlFree(tmp);
65 } else if ((finished == 1) && (xmlStrcmp(node->name,"good_password") == 0)) {
66 tmp = xmlEncodeEntitiesReentrant(status, (const xmlChar*) &password_good);
67 if (node->children)
68 xmlNodeSetContent(node->children, tmp);
69 xmlFree(tmp);
72 xmlMutexUnlock(finishedMutex);
74 xmlSaveFormatFileEnc(statname, status, "UTF-8", 1);
76 return;
79 inline int abcnumb(char a) {
80 int i;
81 for (i = 0; i<ABCLEN; i++)
82 if (ABC[i] == a) return i;
83 return 0;
86 int loadstatus() {
87 xmlNodePtr root = NULL;
88 xmlNodePtr node = NULL;
89 xmlParserCtxtPtr parserctxt;
90 int ret = 0;
91 char* tmp;
92 FILE* totest;
93 totest = fopen(statname, "r");
94 if (totest != NULL) {
95 fclose(totest);
96 status = xmlParseFile(statname);
98 if (status != NULL)
99 root = xmlDocGetRootElement(status);
100 else
101 status = xmlNewDoc(NULL);
102 if (root != 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);
109 } else
110 ret = 1;
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);
118 xmlFree(tmp);
119 } else
120 ret = 1;
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);
128 finished = 1;
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);
133 xmlFree(tmp);
134 ret = 1;
138 xmlFreeParserCtxt(parserctxt);
139 } else {
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", "");
145 savestatus();
147 return ret;
150 void nextpass2(char* p, unsigned int n) {
151 int i;
152 if (p[n] == ABC[ABCLEN-1]) {
153 p[n] = ABC[0];
154 if (n>0)
155 nextpass2(p, n-1);
156 else {
157 for (i=curr_len; i>=0; i--)
158 p[i+1]=p[i];
159 p[0]=ABC[0];
160 p[++curr_len]='\0';
163 } else
164 p[n] = ABC[abcnumb(p[n])+1];
165 return;
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);
174 return ok;
177 void * status_thread() {
178 int pwds;
179 const short status_sleep = 3;
180 while(1) {
181 sleep(status_sleep);
182 xmlMutexLock(finishedMutex);
183 pwds = counter / status_sleep;
184 counter = 0;
185 if (finished != 0)
186 break;
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() {
196 char * current;
197 char ret[200];
198 char cmd[400];
199 FILE * Pipe;
200 while (1) {
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);
209 finished = 1;
210 printf("GOOD: password cracked: '%s'\n", current);
211 xmlMutexUnlock(finishedMutex);
212 savestatus();
213 break;
216 pclose(Pipe);
217 xmlMutexLock(finishedMutex);
218 counter++;
219 if (finished != 0) {
220 xmlMutexUnlock(finishedMutex);
221 break;
223 xmlMutexUnlock(finishedMutex);
224 free(current);
228 void crack_start(unsigned int threads) {
229 pthread_t th[13];
230 unsigned int i;
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);
239 return;
242 void init(int argc, char **argv) {
243 unsigned int i, j;
244 int help = 0;
245 int threads = 2;
246 int archive_type = -1;
247 FILE* totest;
248 char test[300];
249 xmlInitThreads();
250 pwdMutex = xmlNewMutex();
251 finishedMutex = xmlNewMutex();
252 if (argc == 1) {
253 printf("USAGE: rarcrack encrypted_archive.ext [--threads NUM] [--type rar|zip|7z]\n");
254 printf(" For more information please run \"rarcrack --help\"\n");
255 help = 1;
256 } else {
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");
267 help = 1;
268 break;
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;
273 if (threads > 12) {
274 printf("INFO: number of threads adjusted to 12\n");
275 threads = 12;
277 } else {
278 printf("ERROR: missing parameter for option: --threads!\n");
279 help = 1;
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]);
287 archive_type = j;
288 break;
291 if (archive_type < 0) {
292 printf("WARNING: invalid parameter --type %s!\n", argv[i]);
293 finalcmd[0] = '\0';
295 } else {
296 printf("ERROR: missing parameter for option: --type!\n");
297 help = 1;
299 } else {
300 strcpy((char*)&filename, argv[i]);
304 if (help == 1)
305 return;
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");
311 return;
312 } else
313 fclose(totest);
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);
318 pclose(totest);
319 for (i = 0; strcmp(MIME[i],"") != 0; i++) {
320 if (strcmp(MIME[i],test) == 0) {
321 strcpy(finalcmd,CMD[i]);
322 archive_type = i;
323 break;
326 printf("INFO: detected file type: %s\n", TYPE[archive_type]);
327 } else
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");
331 return;
332 } /*else
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);
337 return;
339 ABCLEN = strlen(ABC);
340 if (password[0] == '\0')
341 password[0] = ABC[0];
342 crack_start(threads);
343 return;
346 int main(int argc, char *argv[]) {
347 printf("RarCrack! 0.2 by David Zoltan Kedves (kedazo@gmail.com)\n\n");
348 init(argc,argv);
349 if (ABC != (char*) &default_ABC)
350 xmlFree(ABC);
351 if (status)
352 xmlFreeDoc(status);
353 xmlFreeMutex(pwdMutex);
354 xmlFreeMutex(finishedMutex);
355 return EXIT_SUCCESS;