Skip to content

Instantly share code, notes, and snippets.

@esterTion
Last active April 28, 2025 19:06
Show Gist options
  • Save esterTion/768c646a83a089af9e5fbb83b77a59fc to your computer and use it in GitHub Desktop.
Save esterTion/768c646a83a089af9e5fbb83b77a59fc to your computer and use it in GitHub Desktop.
Bang Dream proto dumper
gist title place holder

Used to dump proto defination from BangDream, meant to dump ios binary

First, modify Il2Cpp (like using dnspy) to dump Properties. (Config.dumpProperty = true)
Then dump the game as usual
Modify generateMessage.php to match your binary and dump.cs file
And run php generateMessage.php <messageClass>

Example proto output attached

Notice: Dictionary is outputed as two elements message, 1 for key, and 2 for value


用于导出BangDream proto定义文件,可用在ios程序上
首先修改Il2Cpp(比如用dnspy)使之导出属性(Config.dumpProperty = true)
然后导出程序内容
修改 generateMessage.php内的程序与 dump.cs 文件位置
然后运行 php generateMessage.php <messageClass>

后附样例proto输出

注意:Dictionary 键值对输出为两元素结构,1为键,2为值

<?php
/**
* https://gist.github.com/esterTion/768c646a83a089af9e5fbb83b77a59fc
* Updated for il2cpp-dumper v6.1.2
* https://github.com/Perfare/Il2CppDumper/releases
*/
$dumpcs = file_get_contents('D:\\ida_workplace\\bang\\dump.cs');
$prog = fopen('D:\\ida_workplace\\bang\\UnityFramework','rb');
$definedClass=[];
$class = $argv[1];
$outputProtoFile = fopen(__DIR__.'/'.$class.'_gen.proto', 'w');
fwrite($outputProtoFile, "syntax = \"proto2\";\n");
function stripClass($s) {
$idx = strrpos($s, '.');
if ($idx === false) return $s;
return substr($s, $idx + 1);
}
function writeMessage($class, $message) {
global $outputProtoFile;
$class = stripClass($class);
fwrite($outputProtoFile, "message ${class} {\n");
foreach ($message as $item=>$info) {
$type = stripClass($info[0]);
$tag = $info[1];
$hint = $info[2];
$comment = $info[3];
fwrite($outputProtoFile, " ${hint} ${type} ${item} = ${tag}; // ${comment}\n");
}
fwrite($outputProtoFile, "}\n");
}
function readClass($level, $class) {
global $dumpcs;
global $definedClass;
if (($shownClass = array_search($class, $definedClass)) === false) {
$definedClass[] = $class;
}
$message = [];
//echo str_repeat(" ", $level).$class."\n";
if (preg_match("(\[ProtoContract\].*\n\w+ class ".$class." [^{}]*?(\{((?>[^{}]+)|(?-2))*\}))", $dumpcs, $classDef) !== 0) {
$classDef=$classDef[0];
preg_match_all('(\[ProtoMember\((\d+)\)\].*\n \w+ ([^\ \<]+(\<((?>[^\<\>]+)|(?-2))*\>)?) ([^\ ;]+))', $classDef, $propList);
for($i=0;$i<count($propList[0]); $i++) {
$type = jumpType(
$level,
$propList[2][$i],
$propList[5][$i]
);
$message[$type[0]] = [$type[1], $propList[1][$i], $type[2], $type[3]];
}
if ($class == 'MasterActionSet') {
$message['areaName'] = [
'string',
6,
'optional',
'manual add'
];
}
if (!$shownClass) {
echo $class."\n";
//print_r($message);
writeMessage($class, $message);
}
unset($message);
} else {
echo $class.' not found';
exit;
}
}
// 1012ECB5C 1
// 1012ECB70 2
function jumpType ($level, $type, $name) {
if (substr($type, -2, 2) == '[]') {
// array entry
//echo str_repeat(" ", $level+1).$type."\n";
$sub = jumpType($level+2, substr($type, 0, -2), 'entry');
return [$name, $sub[1], 'repeated', 'array'];
} else if (substr($type, 0, 11) == 'Dictionary<') {
// dictionary
preg_match('(<(\w+), (\w+)>)', $type, $subType);
//echo str_repeat(" ", $level+1).'dictarr_'.$name."[]\n";
$prefix = $subType[1].'_'.$subType[2];
global $definedClass;
if (($shownClass = array_search($prefix, $definedClass)) === false) {
$definedClass[] = $prefix;
}
$message = [];
$sub = jumpType($level+1, $subType[1], $prefix.'_key');
$message[$sub[0]] = [$sub[1], 1, $sub[2], $sub[3]];
$sub = jumpType($level+1, $subType[2], $prefix.'_value');
$message[$sub[0]] = [$sub[1], 2, $sub[2], $sub[3]];
if (!$shownClass) {
writeMessage($prefix, $message);
}
return [$name,$prefix, 'repeated', 'dictionary'];
} else if (substr($type, 0, 5) == 'List<') {
// array entry
preg_match('(<(\w+)>)', $type, $subType);
//echo str_repeat(" ", $level+1).'arr_'.$name."[]\n";
$sub = jumpType($level+1, $subType[1], 'entry');
return [$name,$sub[1], 'repeated', 'list'];
} else if (array_search($type,
['uint','string','ulong','float','int','double', 'bool','long']
) !== false){
// normal type
//echo str_repeat(" ", $level+1).'<'.$type .'> '. $name."\n";
return [$name,array('uint'=>'uint32','string'=>'string','ulong'=>'uint64','float'=>'float','int'=>'int32','double'=>'double', 'bool'=>'bool','long'=>'int64')[$type], 'optional', 'normal type'];
} else if (substr($type, 0, 9) == 'Nullable<') {
// array entry
//echo str_repeat(" ", $level+1).'<'.$type .'> '. $name."\n";
//return [$name,$type, 'optional', 'nullable type'];
preg_match('(<(\w+)>)', $type, $subType);
$return = jumpType($level, $subType[1], $name);
$return[3] = 'nullable';
return $return;
} else {
// sub message
readClass($level+1, $type);
return [$name,$type, 'optional', 'sub class'];
}
}
readClass(0, $class);
@dlbuhtig4096
Copy link

dlbuhtig4096 commented Jan 31, 2025

@esterTion 原來如此,怪不得都抓不到 我還奇怪為什麼代理設定看起來都沒有作用 ServerConfig 這個 class 我再研究看看,謝謝
我好像有在 /1cc/ 看過你和其他人的討論 如果你對這遊戲有興趣的話,我之後可以分享 proto dumper 和加解密的 code

I’ve been working hard trying to capture the messages from Pokémon TCG Pocket. I tried everything—Charles, MITM, Burp. I got the global-metadata and managed to extract the DLLs (both iOS and Android), but I couldn’t create a Frida script that hooks the functions correctly without crashing, nor could I extract data from the sent/received packets.

With IDA, I found the certificates, but I couldn’t make any further progress.

If you managed to read the packets, could you give me a hand?

My Discord is 0xs4d.

@0xS4D I haven't get packets capture working yet.
Was working on dumping proto from the game.
And I am almost there, dumped protos are publicly available in this repo.

Actually I have tried Frida few days ago and it crashed as well.
I will probably give frida-il2cpp-bridge a try few days later.
Have send you friend request on discord.

@esterTion 就像上面說的,我開了一個 public repo
現在只有 proto,順利的話之後會做個 python client 然後開源在上面
不過我通常只逆向單機遊戲,不太碰網遊
所以別說 grpc 了,我連一般的 rpc 都沒怎麼碰過,只知道個大概
其他人也都是第一次碰 grpc

如果有個熟悉通訊的人在,相信這個 project 容易很多
有興趣一起研究的話,請再通知我們一聲

@andreacanes
Copy link

andreacanes commented Feb 16, 2025

Hey guys very interested in your work, I was wondering if you'd like to connect and talk about this, I know a few weeks went by but I would to discuss this with someone like you, I have gotten pretty far, and I managed to decompile the apk and dump dlls and classes and methods with il2cpp-bridge.
If you want to use frida I have been able to only successfully set it up on 1 emulator, everything else seem to not work or if it does it still won't let you access the emulated realm for il2cpp-bridge.
@dlbuhtig4096 Would it be possible to access the dumped proto you mentioned? I'm about to dive into that and it would save me some time. I would also love to work with you on the replicating request part as that is where I have lots of previous experience.
@0xS4D I also sent you a friend request if you'd be interesting in working on this

My expertise is more on the side of rebuilding and replicating requests but I had lots of fun getting my hands on something new.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment