Initial clone

This commit is contained in:
Lesbian 2018-10-03 11:28:44 -04:00
commit e8252b0f32
8 changed files with 723 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
clownflare
*.o
*.core

16
LICENSE Normal file
View File

@ -0,0 +1,16 @@
ISC License
Copyright (c) 2018 Hiltjo Posthuma <hiltjo@codemadness.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

6
Makefile Normal file
View File

@ -0,0 +1,6 @@
build:
cc xml.c clownflare.c -o clownflare -Wall
clean:
rm -f clownflare

10
README Normal file
View File

@ -0,0 +1,10 @@
ugly Cloudflare/clownflare JS challenge cracker
Usage:
pass the HTML source through this program:
clownflare 'someurl' < htmlsource
open the url in your browser.

193
clownflare.c Normal file
View File

@ -0,0 +1,193 @@
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifdef __OpenBSD__
#include <unistd.h>
#else
#define pledge(a,b) 0
#endif
#include "xml.h"
static XMLParser x;
static char tag[256], inputname[256];
static char jschl_vc[256];
static char jschl_answer[256];
static char pass[256];
static char script[4096];
void
xmltagstart(struct xmlparser *x, const char *t, size_t tl)
{
if (!strcmp(t, "input") || !strcmp(t, "script"))
snprintf(tag, sizeof(tag), "%s", t);
}
void
xmltagend(struct xmlparser *x, const char *t, size_t tl, int st)
{
if (!strcmp(tag, "input"))
inputname[0] = tag[0] = '\0';
else if (!strcmp(tag, "script"))
tag[0] = '\0';
}
void
xmlattr(struct xmlparser *x, const char *t, size_t tl,
const char *a, size_t al, const char *v, size_t vl)
{
if (strcmp(tag, "input"))
return;
if (!strcmp(a, "name")) {
if (!strcmp(v, "jschl_vc") || !strcmp(v, "pass"))
snprintf(inputname, sizeof(inputname), "%s", v);
} else if (inputname[0] && !strcmp(a, "value")) {
if (!strcmp(inputname, "jschl_vc"))
snprintf(jschl_vc, sizeof(jschl_vc), "%s", v);
else if (!strcmp(inputname, "pass"))
snprintf(pass, sizeof(pass), "%s", v);
}
}
void
xmlcdata(struct xmlparser *x, const char *d, size_t dl)
{
char tmp[sizeof(script)];
if (strcmp(tag, "script"))
return;
snprintf(tmp, sizeof(tmp), "%s%s", script, d);
memcpy(script, tmp, sizeof(script));
}
int
calcvalue(char *script)
{
char *stopbreaking = "s,t,o,p,b,r,e,a,k,i,n,g,f, ";
char var[32] = "", key[32] = "", varkey[64] = "";
char *p, *s;
int op, pc, cv, nv, v = 0;
if (!(s = strstr(script, stopbreaking)))
return v;
s += strlen(stopbreaking);
for (p = s; *p; p++) {
if (*p == '=') {
*p = '\0';
snprintf(var, sizeof(var), "%s", s);
*p = '=';
break;
}
}
if (!var[0])
return v;
if (!(s = strchr(p, '"')))
return v;
s++;
for (p = s; *p; p++) {
if (*p == '"') {
*p = '\0';
snprintf(key, sizeof(key), "%s", s);
*p = '"';
break;
}
}
if (!key[0])
return v;
snprintf(varkey, sizeof(varkey), "%s.%s", var, key);
if (!(s = strchr(p, ':')))
return v;
s++;
op = '+';
while (1) {
// printf("op: %c\n", op);
pc = cv = nv = 0;
for (s = p; *s; s++) {
if (*s == ';') {
nv += cv;
// printf("nv: %d\n", nv);
break;
}
switch (*s) {
case '(':
nv += cv;
cv = 0;
break;
case '!':
case '+':
if (pc == '!')
cv++;
break;
case ')':
if (pc == ')')
break;
// printf(" cv: %d\n", cv);
nv *= 10;
break;
}
// printf(" %c\n", *s);
pc = *s;
}
switch (op) {
case '-': v -= nv; break;
case '+': v += nv; break;
case '*': v *= nv; break;
}
if (!(s = strstr(p, varkey)))
return v;
p = s + strlen(varkey);
op = *p;
}
return v;
}
int
main(int argc, char *argv[])
{
int value;
if (pledge("stdio", NULL) < 0)
err(1, "pledge");
if (argc != 2) {
fprintf(stderr, "%s <hostname>\n", argv[0]);
return 1;
}
x.xmlattr = xmlattr;
x.xmlcdata = xmlcdata;
x.xmltagstart = xmltagstart;
x.xmltagend = xmltagend;
x.getnext = getchar;
xml_parse(&x);
if (!(value = calcvalue(script)))
return 1;
value += strlen(argv[1]);
snprintf(jschl_answer, sizeof(jschl_answer), "%d", value);
printf("jschl_vc = %s\n", jschl_vc);
printf("pass = %s\n", pass);
printf("jschl_answer = %s\n", jschl_answer);
printf("\n");
printf("https://%s/cdn-cgi/l/chk_jschl?jschl_vc=%s&pass=%s&jschl_answer=%s\n",
argv[1], jschl_vc, pass, jschl_answer);
return 0;
}

2
test.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
curl -m 10 -H 'User-Agent:' 'https://torrentz2.eu/' | ./clownflare "torrentz2.eu"

447
xml.c Normal file
View File

@ -0,0 +1,447 @@
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xml.h"
static void
xml_parseattrs(XMLParser *x)
{
size_t namelen = 0, valuelen;
int c, endsep, endname = 0;
while ((c = x->getnext()) != EOF) {
if (isspace(c)) { /* TODO: simplify endname ? */
if (namelen)
endname = 1;
continue;
}
if (c == '?')
; /* ignore */
else if (c == '=') {
x->name[namelen] = '\0';
} else if (namelen && ((endname && isalpha(c)) || (c == '>' || c == '/'))) {
/* attribute without value */
x->name[namelen] = '\0';
if (x->xmlattrstart)
x->xmlattrstart(x, x->tag, x->taglen, x->name, namelen);
if (x->xmlattr)
x->xmlattr(x, x->tag, x->taglen, x->name, namelen, "", 0);
if (x->xmlattrend)
x->xmlattrend(x, x->tag, x->taglen, x->name, namelen);
endname = 0;
x->name[0] = c;
namelen = 1;
} else if (namelen && (c == '\'' || c == '"')) {
/* attribute with value */
endsep = c; /* c is end separator */
if (x->xmlattrstart)
x->xmlattrstart(x, x->tag, x->taglen, x->name, namelen);
for (valuelen = 0; (c = x->getnext()) != EOF;) {
if (c == '&') { /* entities */
x->data[valuelen] = '\0';
/* call data function with data before entity if there is data */
if (valuelen && x->xmlattr)
x->xmlattr(x, x->tag, x->taglen, x->name, namelen, x->data, valuelen);
x->data[0] = c;
valuelen = 1;
while ((c = x->getnext()) != EOF) {
if (c == endsep)
break;
if (valuelen < sizeof(x->data) - 1)
x->data[valuelen++] = c;
else {
/* TODO: entity too long? this should be very strange. */
x->data[valuelen] = '\0';
if (x->xmlattr)
x->xmlattr(x, x->tag, x->taglen, x->name, namelen, x->data, valuelen);
valuelen = 0;
break;
}
if (c == ';') {
x->data[valuelen] = '\0';
if (x->xmlattrentity)
x->xmlattrentity(x, x->tag, x->taglen, x->name, namelen, x->data, valuelen);
valuelen = 0;
break;
}
}
} else if (c != endsep) {
if (valuelen < sizeof(x->data) - 1) {
x->data[valuelen++] = c;
} else {
x->data[valuelen] = '\0';
if (x->xmlattr)
x->xmlattr(x, x->tag, x->taglen, x->name, namelen, x->data, valuelen);
x->data[0] = c;
valuelen = 1;
}
}
if (c == endsep) {
x->data[valuelen] = '\0';
if (x->xmlattr)
x->xmlattr(x, x->tag, x->taglen, x->name, namelen, x->data, valuelen);
if (x->xmlattrend)
x->xmlattrend(x, x->tag, x->taglen, x->name, namelen);
break;
}
}
namelen = endname = 0;
} else if (namelen < sizeof(x->name) - 1) {
x->name[namelen++] = c;
}
if (c == '>') {
break;
} else if (c == '/') {
x->isshorttag = 1;
namelen = 0;
x->name[0] = '\0';
}
}
}
static void
xml_parsecomment(XMLParser *x)
{
size_t datalen = 0, i = 0;
int c;
if (x->xmlcommentstart)
x->xmlcommentstart(x);
while ((c = x->getnext()) != EOF) {
if (c == '-' || c == '>') {
if (x->xmlcomment) {
x->data[datalen] = '\0';
x->xmlcomment(x, x->data, datalen);
datalen = 0;
}
}
if (c == '-') {
if (++i > 2) {
if (x->xmlcomment)
for (; i > 2; i--)
x->xmlcomment(x, "-", 1);
i = 2;
}
continue;
} else if (c == '>' && i == 2) {
if (x->xmlcommentend)
x->xmlcommentend(x);
return;
} else if (i) {
if (x->xmlcomment) {
for (; i > 0; i--)
x->xmlcomment(x, "-", 1);
}
i = 0;
}
if (datalen < sizeof(x->data) - 1) {
x->data[datalen++] = c;
} else {
x->data[datalen] = '\0';
if (x->xmlcomment)
x->xmlcomment(x, x->data, datalen);
x->data[0] = c;
datalen = 1;
}
}
}
static void
xml_parsecdata(XMLParser *x)
{
size_t datalen = 0, i = 0;
int c;
if (x->xmlcdatastart)
x->xmlcdatastart(x);
while ((c = x->getnext()) != EOF) {
if (c == ']' || c == '>') {
if (x->xmlcdata) {
x->data[datalen] = '\0';
x->xmlcdata(x, x->data, datalen);
datalen = 0;
}
}
if (c == ']') {
if (++i > 2) {
if (x->xmlcdata)
for (; i > 2; i--)
x->xmlcdata(x, "]", 1);
i = 2;
}
continue;
} else if (c == '>' && i == 2) {
if (x->xmlcdataend)
x->xmlcdataend(x);
return;
} else if (i) {
if (x->xmlcdata)
for (; i > 0; i--)
x->xmlcdata(x, "]", 1);
i = 0;
}
if (datalen < sizeof(x->data) - 1) {
x->data[datalen++] = c;
} else {
x->data[datalen] = '\0';
if (x->xmlcdata)
x->xmlcdata(x, x->data, datalen);
x->data[0] = c;
datalen = 1;
}
}
}
int
xml_codepointtoutf8(uint32_t cp, uint32_t *utf)
{
if (cp >= 0x10000) {
/* 4 bytes */
*utf = 0xf0808080 | ((cp & 0xfc0000) << 6) |
((cp & 0x3f000) << 4) | ((cp & 0xfc0) << 2) |
(cp & 0x3f);
return 4;
} else if (cp >= 0x00800) {
/* 3 bytes */
*utf = 0xe08080 |
((cp & 0x3f000) << 4) | ((cp & 0xfc0) << 2) |
(cp & 0x3f);
return 3;
} else if (cp >= 0x80) {
/* 2 bytes */
*utf = 0xc080 |
((cp & 0xfc0) << 2) | (cp & 0x3f);
return 2;
}
*utf = cp & 0xff;
return *utf ? 1 : 0; /* 1 byte */
}
ssize_t
xml_namedentitytostr(const char *e, char *buf, size_t bufsiz)
{
static const struct {
char *entity;
int c;
} entities[] = {
{ .entity = "&amp;", .c = '&' },
{ .entity = "&lt;", .c = '<' },
{ .entity = "&gt;", .c = '>' },
{ .entity = "&apos;", .c = '\'' },
{ .entity = "&quot;", .c = '"' },
{ .entity = "&AMP;", .c = '&' },
{ .entity = "&LT;", .c = '<' },
{ .entity = "&GT;", .c = '>' },
{ .entity = "&APOS;", .c = '\'' },
{ .entity = "&QUOT;", .c = '"' }
};
size_t i;
/* buffer is too small */
if (bufsiz < 2)
return -1;
/* doesn't start with &: can't match */
if (*e != '&')
return 0;
for (i = 0; i < sizeof(entities) / sizeof(*entities); i++) {
if (!strcmp(e, entities[i].entity)) {
buf[0] = entities[i].c;
buf[1] = '\0';
return 1;
}
}
return 0;
}
ssize_t
xml_numericentitytostr(const char *e, char *buf, size_t bufsiz)
{
uint32_t l = 0, cp = 0;
size_t b, len;
char *end;
/* buffer is too small */
if (bufsiz < 5)
return -1;
/* not a numeric entity */
if (e[0] != '&' || e[1] != '#')
return 0;
/* e[1] == '#', numeric / hexadecimal entity */
e += 2; /* skip "&#" */
errno = 0;
/* hex (16) or decimal (10) */
if (*e == 'x')
l = strtoul(e + 1, &end, 16);
else
l = strtoul(e, &end, 10);
/* invalid value or not a well-formed entity */
if (errno || *end != ';')
return 0;
len = xml_codepointtoutf8(l, &cp);
/* make string */
for (b = 0; b < len; b++)
buf[b] = (cp >> (8 * (len - 1 - b))) & 0xff;
buf[len] = '\0';
return (ssize_t)len;
}
/* convert named- or numeric entity string to buffer string
* returns byte-length of string. */
ssize_t
xml_entitytostr(const char *e, char *buf, size_t bufsiz)
{
/* buffer is too small */
if (bufsiz < 5)
return -1;
/* doesn't start with & */
if (e[0] != '&')
return 0;
/* named entity */
if (e[1] != '#')
return xml_namedentitytostr(e, buf, bufsiz);
else /* numeric entity */
return xml_numericentitytostr(e, buf, bufsiz);
}
void
xml_parse(XMLParser *x)
{
int c, ispi;
size_t datalen, tagdatalen, taglen;
if (!x->getnext)
return;
while ((c = x->getnext()) != EOF && c != '<')
; /* skip until < */
while (c != EOF) {
if (c == '<') { /* parse tag */
if ((c = x->getnext()) == EOF)
return;
x->tag[0] = '\0';
x->taglen = 0;
if (c == '!') { /* cdata and comments */
for (tagdatalen = 0; (c = x->getnext()) != EOF;) {
if (tagdatalen <= sizeof("[CDATA[") - 1) /* if (d < sizeof(x->data)) */
x->data[tagdatalen++] = c; /* TODO: prevent overflow */
if (c == '>')
break;
else if (c == '-' && tagdatalen == sizeof("--") - 1 &&
(x->data[0] == '-')) {
xml_parsecomment(x);
break;
} else if (c == '[') {
if (tagdatalen == sizeof("[CDATA[") - 1 &&
!strncmp(x->data, "[CDATA[", tagdatalen)) {
xml_parsecdata(x);
break;
}
}
}
} else {
/* normal tag (open, short open, close), processing instruction. */
if (isspace(c))
while ((c = x->getnext()) != EOF && isspace(c))
;
if (c == EOF)
return;
x->tag[0] = c;
ispi = (c == '?') ? 1 : 0;
x->isshorttag = ispi;
taglen = 1;
while ((c = x->getnext()) != EOF) {
if (c == '/') /* TODO: simplify short tag? */
x->isshorttag = 1; /* short tag */
else if (c == '>' || isspace(c)) {
x->tag[taglen] = '\0';
if (x->tag[0] == '/') { /* end tag, starts with </ */
x->taglen = --taglen; /* len -1 because of / */
if (taglen && x->xmltagend)
x->xmltagend(x, &(x->tag)[1], x->taglen, 0);
} else {
x->taglen = taglen;
/* start tag */
if (x->xmltagstart)
x->xmltagstart(x, x->tag, x->taglen);
if (isspace(c))
xml_parseattrs(x);
if (x->xmltagstartparsed)
x->xmltagstartparsed(x, x->tag, x->taglen, x->isshorttag);
}
/* call tagend for shortform or processing instruction */
if ((x->isshorttag || ispi) && x->xmltagend)
x->xmltagend(x, x->tag, x->taglen, 1);
break;
} else if (taglen < sizeof(x->tag) - 1)
x->tag[taglen++] = c;
}
}
} else {
/* parse tag data */
datalen = 0;
if (x->xmldatastart)
x->xmldatastart(x);
while ((c = x->getnext()) != EOF) {
if (c == '&') {
if (datalen) {
x->data[datalen] = '\0';
if (x->xmldata)
x->xmldata(x, x->data, datalen);
}
x->data[0] = c;
datalen = 1;
while ((c = x->getnext()) != EOF) {
if (c == '<')
break;
if (datalen < sizeof(x->data) - 1)
x->data[datalen++] = c;
if (isspace(c))
break;
else if (c == ';') {
x->data[datalen] = '\0';
if (x->xmldataentity)
x->xmldataentity(x, x->data, datalen);
datalen = 0;
break;
}
}
} else if (c != '<') {
if (datalen < sizeof(x->data) - 1) {
x->data[datalen++] = c;
} else {
x->data[datalen] = '\0';
if (x->xmldata)
x->xmldata(x, x->data, datalen);
x->data[0] = c;
datalen = 1;
}
}
if (c == '<') {
x->data[datalen] = '\0';
if (x->xmldata && datalen)
x->xmldata(x, x->data, datalen);
if (x->xmldataend)
x->xmldataend(x);
break;
}
}
}
}
}

45
xml.h Normal file
View File

@ -0,0 +1,45 @@
typedef struct xmlparser {
/* handlers */
void (*xmlattr)(struct xmlparser *, const char *, size_t,
const char *, size_t, const char *, size_t);
void (*xmlattrend)(struct xmlparser *, const char *, size_t,
const char *, size_t);
void (*xmlattrstart)(struct xmlparser *, const char *, size_t,
const char *, size_t);
void (*xmlattrentity)(struct xmlparser *, const char *, size_t,
const char *, size_t, const char *, size_t);
void (*xmlcdatastart)(struct xmlparser *);
void (*xmlcdata)(struct xmlparser *, const char *, size_t);
void (*xmlcdataend)(struct xmlparser *);
void (*xmlcommentstart)(struct xmlparser *);
void (*xmlcomment)(struct xmlparser *, const char *, size_t);
void (*xmlcommentend)(struct xmlparser *);
void (*xmldata)(struct xmlparser *, const char *, size_t);
void (*xmldataend)(struct xmlparser *);
void (*xmldataentity)(struct xmlparser *, const char *, size_t);
void (*xmldatastart)(struct xmlparser *);
void (*xmltagend)(struct xmlparser *, const char *, size_t, int);
void (*xmltagstart)(struct xmlparser *, const char *, size_t);
void (*xmltagstartparsed)(struct xmlparser *, const char *,
size_t, int);
int (*getnext)(void);
/* current tag */
char tag[1024];
size_t taglen;
/* current tag is in short form ? <tag /> */
int isshorttag;
/* current attribute name */
char name[256];
/* data buffer used for tag data, cdata and attribute data */
char data[BUFSIZ];
} XMLParser;
int xml_codepointtoutf8(uint32_t, uint32_t *);
ssize_t xml_entitytostr(const char *, char *, size_t);
ssize_t xml_namedentitytostr(const char *, char *, size_t);
ssize_t xml_numericentitytostr(const char *, char *, size_t);
void xml_parse(XMLParser *);