Skip to content
Create a gist now

Instantly share code, notes, and snippets.

anonymous /dump.py secret
Created Oct 5, 2015

# -*- coding: utf-8 -*-
from string import ascii_letters, digits
from warnings import filterwarnings
from random import randint, choice
from pprint import pprint
from time import sleep
import webbrowser
import argparse
import requests
import json
import sys
import os
import re
py3 = sys.version_info[0] > 2
filterwarnings('ignore')
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
# https://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python/312464#312464
def natural_sort(l):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(l, key=alphanum_key)
# https://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort/4836734#4836734
def has_numbers(input_string):
return any(char.isdigit() for char in input_string)
# https://stackoverflow.com/questions/19859282/check-if-a-string-contains-a-number/19859308#19859308
def fetch_captcha():
r = requests.get('https://8ch.net/8chan-captcha/entrypoint.php?mode=get&extra=abcdefghijklmnopqrstuvwxyz&nojs=true')
try:
match = 'CAPTCHA ID: [a-z]*'
captcha_cookie = re.search(match, r.text).group().split(': ')[1]
match = '<image src="data:image/png;base64,[A-Za-z0-9+/=]*">'
with open('captcha_image.png', 'wb') as f:
f.write(re.search(match, r.text).group().split(',')[1].strip('>').strip('"').decode('base64'))
webbrowser.open('captcha_image.png')
if py3:
captcha_text = input('Enter the captcha: ')
else:
captcha_text = raw_input('Enter the captcha: ')
os.remove('captcha_image.png')
data['captcha_cookie'] = captcha_cookie
data['captcha_text'] = captcha_text
except AttributeError:
print('Server error while fetching captcha')
pass
parser = argparse.ArgumentParser(description='Dump a folder to a thread')
parser.add_argument('-f', '--folder', help='Folder to upload images from', type=str, required=True)
parser.add_argument('-u', '--url', help='URL of thread', required=True)
parser.add_argument('-d', '--delay', help='Delay between posting', type=int, required=True)
parser.add_argument('-i', '--images', help='Number of images to post', type=int)
parser.add_argument('-n', '--name', help='Name to post with', type=str, default='')
parser.add_argument('-e', '--email', help='Email to post with', type=str, default='')
parser.add_argument('-p', '--progress', help='Post with dump progress? (default y)', choices=('y', 'n'), default='y')
parser.add_argument('-r', '--random', help='Post with random filenames? (default n)', choices=('y', 'n'), default='n')
parser.add_argument('-l', '--length', help='To be used with -r/--random. Maximum length of random filename (optional, default 15)', type=int, default=15)
args = vars(parser.parse_args())
# https://stackoverflow.com/questions/9234258/in-python-argparse-is-it-possible-to-have-paired-no-something-something-arg
def make_random_filename():
splitfilename = l[file].split('.')
extension = splitfilename[len(splitfilename) - 1]
return ''.join(choice(ascii_letters + digits) for _ in range(randint(1, args['length']))) + '.' + extension
delay = args['delay']
DIRECTORY = args['folder']
filelist = []
for file in os.listdir(DIRECTORY):
if os.path.splitext(file)[1].lower() in ('.jpg', '.jpeg', '.png', '.gif', '.webm', '.mp4'):
filelist.append(os.path.join(DIRECTORY, file))
# I stole this from stackoverflow somewhere, I can't find the link
if len(args['url'].split('/')) == 6:
spliturl = args['url'].split('/')
if has_numbers(spliturl[5]) and '.html' in args['url']:
url = '{}//{}'.format(spliturl[0], spliturl[2])
board = spliturl[3]
thread = spliturl[5].split('.')[0]
else:
sys.exit('\nBad URL. --u/--url should be the URL of a thread.\nExample: https://8ch.net/b/res/1.html')
else:
sys.exit('\nBad URL. --u/--url should be the URL of a thread.\nExample: https://8ch.net/b/res/1.html')
boardindex = requests.get('{}/{}/index.html'.format(url, board))
if boardindex.status_code == 200:
# this is a terrible idea and searching HTML for strings/using regular expressions should never be done
# BUT, since 8chan goes overkill on escaping, this is guaranteed to be the only match
match = '<script type="text/javascript">var configRoot="/";[a-zA-Z0-9;=+()/"?:._ ]*'
maxfiles = int(re.search(match, boardindex.text).group().split(';')[3].split('=')[1])
if '<script>load_captcha("https://8ch.net/8chan-captcha/entrypoint.php", "abcdefghijklmnopqrstuvwxyz")' in boardindex.text:
captcha = True
else:
captcha = False
else:
sys.exit('Error fetching board index/Unable to retrieve board settings')
if args['images'] == None:
print('-i/--images not specified. Defaulting to the maximum number of allowed images on this board.')
else:
if args['images'] >= 1 and args['images'] <= 5:
maxfiles = args['images']
else:
sys.exit('-i/--images must be between 1 and 5')
filelist = natural_sort(filelist)
total = len(filelist)
chunked_list = list(chunks(filelist, maxfiles))
data = {
'board': board,
'thread': thread,
'name': args['name'],
'email': args['email'],
'subject': '',
'body': '',
'embed': '',
'dx': '',
'dy': '',
'dz': '',
'password': 'ayylmao',
'json_response': '1',
'post': 'New Reply',
}
headers = {
'referer': '',
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'cache-control': 'max-age=0',
}
headers['referer'] = '{}/{}/'.format(url, board)
def fetch_dnsbl_captcha():
r = requests.get('https://8ch.net/dnsbls_bypass.php').text
try:
match = "value='[a-z]*"
captcha_cookie = re.search(match, r).group().split("'")[1]
match = '<image src="data:image/png;base64,[A-Za-z0-9+/=]*">'
with open('dnsbl_captcha_image.png', 'wb') as f:
f.write(re.search(match, r).group().split('"')[1].split(',')[1].decode('base64'))
webbrowser.open('dnsbl_captcha_image.png')
if py3:
captcha_text = input('Enter the captcha: ')
else:
captcha_text = raw_input('Enter the captcha: ')
os.remove('dnsbl_captcha_image.png')
dnsbl_data = {}
dnsbl_data['captcha_cookie'] = captcha_cookie
dnsbl_data['captcha_text'] = captcha_text
r = requests.post('{}/dnsbls_bypass.php'.format(url), data=dnsbl_data, headers=headers)
except AttributeError:
print('Server error while fetching captcha')
pass
# no
# bad anon
# STOP
progress = maxfiles
for chunk in range(len(chunked_list)):
number_of_files = len(chunked_list[chunk])
status = ''
while 'redirect' not in status:
for x in range(len(chunked_list[chunk])):
l = natural_sort(chunked_list[chunk])
files = []
if args['random'] == 'y':
for file in range(len(l)):
if file == 0:
files.append(['file', (make_random_filename(), open(l[file], 'rb'))])
else:
files.append(['file' + str(file), (make_random_filename(), open(l[file], 'rb'))])
else:
for file in range(len(l)):
if file == 0:
files.append(['file', open(l[file], 'rb')])
else:
files.append(['file' + str(file), open(l[file], 'rb')])
files = tuple(files)
if progress > total:
progress = total
if args['progress'] == 'y':
data['body'] = '{}/{}'.format(progress, total)
else:
data['body'] =''
if captcha is True:
fetch_captcha()
r = requests.post('{}/post.php'.format(url), data=data, headers=headers, files=files)
status_code = r.status_code
status = r.text
if status_code == 200:
print(status)
else:
print('{} server error'.format(status_code))
if 'dnsbls_bypass.php' in status:
fetch_dnsbl_captcha()
if 'Failed to resize image' and 'corrupt image' in status or 'XSS' in status:
print('ONE OF THE FOLLOWING IMAGES ARE CORRUPT, AND AS A RESULT, THE FOLLOWING FILES WERE NOT UPLOADED:')
pprint(l)
status = 'redirect'
if 'already exists' in status:
status = 'redirect'
if 'Maximum file size' in status:
print('THE FOLLOWING FILE(S) WERE OVER THE FILE SIZE LIMIT AND WERE NOT POSTED:')
pprint(l)
print('Consider setting -i/--images to a lower number so your files fit under the limit')
status = 'redirect'
del files
print('{}/{} - Waiting {} seconds...').format(progress, total, delay)
sleep(delay)
progress += number_of_files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.