Henry's Notebook
Many strange things
搜索
菜单
导航
首页
最近更改
随机页面
帮助
Henry's Home
个人资料
个人资料
创建账户
登录
消息
目前您没有通知。请访问您的
讨论页
以查看过去消息。
页面工具
内容页面
讨论
查看源代码
历史
首页
»
页面s
查看“AFS file”的源代码
←
AFS file
页面上次由
HenryHu
编辑于12年前
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:emailconfirmed
您可以查看与复制此页面的源代码。
某文件格式 == 文件头 == Endian: Little Endian <source lang="asm"> 0x0000 Signature: AFS\0 0x0004 31 01 00 00 -> 0x131 = 305: record count 0x0008 00 10 00 00 -> 1st start: 0x1000 0x000C 7F 13 00 00 -> 1st size: 0x137F 0x0010 00 28 00 00 -> 2nd start: 0x2800 0x0014 B8 3D 00 00 -> 2nd size: 0x3DB8 .... </source> 最后一组之后:可能有文件索引的start & size,也可能没有…… 替代方法:从最后一个末尾往后找第一个非0的地方…… == 文件索引 == 在文件末尾,索引项大小: 0x30 = 48字节 <source lang="asm"> 1st record: 0x2C6000 BAD.BIP 00..00 0x2C6020 D9 07 08 00 -> 不明,包内相同,解包无关 0x2C6024 0D 00 0A 00 -> 不明,包内相同,解包无关,0D 0A好像不是那个意思…… 0x2C6028 06 00 20 00 -> 不明,多数递增00 00 02 00,也有不变/突变的情况,解包无关 0x2C602C 31 01 00 00 305 -> file count 貌似是垃圾字段,或者是文件头重复…… 2nd record: 0x2C6030 KA01.BIP 00..00 0x2C6050 D9 07 08 00 0x2C6054 0D 00 0A 00 0x2C6058 06 00 22 00 0x2C605C 00 10 00 00 4096 -> 1st start 3rd record: 0x2C6060 KA02.BIP 00..00 0x2C6080 D9 07 08 00 0x2C6080 0D 00 0A 00 0x2C6080 06 00 24 00 0x2C6080 7F 13 00 00 4991 -> 1st size Last record @ 0x2C9900 Total: 305 = 0x131 records </source> == 文件块 == 貌似先存的是索引里的偶数文件,跳过了第一个…… 反正一样解 <source lang="asm"> Last file start @ 2C5800 -> Guess: Min block size: 0x200 = 512 bytes 1st / 2nd start @ 0x1000 -? 0x237F size: 0x137F -> KA02.BIP next start @ 0x2800 diff: 0x4000 -? 0x65B8 size: 0x3DB8 -> KA04.BIP next start @ 0x6800 diff: 0x4000 size: 0xC63C -> KA06.BIP next start @ 0xA800 size: 0x379C -> KA08.BIP next start @ 0xE000 -? 0x1335A size: 0x535A diff: 0x5800 -> KAO.BIP next start @ 0x13800 </source> 貌似是用了[[LZSS]]压缩的,块前四字节是原大小,之后是[[LZSS]]压缩结果。大概是0x200对齐,末尾0填充。 == 分析过程 == <pre> mac.afs: found records @ tail 1st filename @ 2C6000 2nd filename @ 2C6030 3rd filename @ 2C6060 -> file record: 0x30 = 48 bytes 1st record: 0x2C6000 BAD.BIP 00..00 0x2C6020 D9 07 08 00 0x2C6024 0D 00 0A 00 0x2C6028 06 00 20 00 -> + 00 00 02 00 0x2C602C 31 01 00 00 305 -> file count? 2nd record: 0x2C6030 KA01.BIP 00..00 0x2C6050 D9 07 08 00 -> static 0x2C6054 0D 00 0A 00 -> static 0x2C6058 06 00 22 00 -> increasing ? 0x2C605C 00 10 00 00 4096 -> 1st start 3rd record: 0x2C6060 KA02.BIP 00..00 0x2C6080 D9 07 08 00 0x2C6080 0D 00 0A 00 0x2C6080 06 00 24 00 0x2C6080 7F 13 00 00 4991 -> 1st size Last record @ 0x2C9900 Total: 305 = 0x131 records Last file start @ 2C5800 -> Min block size: 0x200 = 512 bytes 1st / 2nd start @ 0x1000 -? 0x237F size: 0x137F -> KA02.BIP next start @ 0x2800 diff: 0x4000 -? 0x65B8 size: 0x3DB8 -> KA04.BIP next start @ 0x6800 diff: 0x4000 size: 0xC63C -> KA06.BIP next start @ 0xA800 size: 0x379C -> KA08.BIP next start @ 0xE000 -? 0x1335A size: 0x535A diff: 0x5800 -> KAO.BIP next start @ 0x13800 diff: Header: 0x00 AFS\0 0x0004 31 01 00 00 -> 0x131 = 305: record count 0x0008 00 10 00 00 -> 1st start 0x000C 7F 13 00 00 -> 1st size 0001000: 0823 0000 ff09 0f06 0000 6008 005f 0900 .#........`.._.. 0001010: 0860 fff5 f009 f9f0 ff4c 008c 0012 0319 .`.......L...... 0001020: 00ff 1a00 6580 0100 65a0 ff01 0033 0100 ....e...e....3.. 0001030: 01ff 10bb 3510 e8f3 6400 02eb f0c0 8fff ....5...d....... 0001040: 1e00 0f2b 0231 0fea f165 ff02 5a00 6520 ...+.1...e..Z.e 0x0010 00 28 00 00 -> 2nd start 0x0014 B8 3D 00 00 -> 2nd size 0002800: 0c6d 0000 ff09 0f06 0000 6008 00ff 1203 .m........`..... 0002810: 1900 1a00 6580 ff1e 0065 a001 0033 01bf ....e....e...3.. 0002820: 0001 ff10 0010 e8f3 65ff 0201 0065 2001 ........e....e . 0002830: 0009 ef00 0860 0a19 0009 6014 b619 0001 .....`....`..... 0002840: a0ec f000 0229 0203 be29 021a 6000 004c .....)...)..`..L 0x0018 00 68 00 00 -> 3rd start 0x001C C6 3C 00 00 -> 3rd size 0006800: 6367 0000 ff09 0f06 0000 6008 00df 0900 cg........`..... 0006810: 0860 0af5 f009 60ff 1900 4c00 4f00 5300 .`....`...L.O.S. 0006820: ff74 1065 8001 0065 a0ff 0100 3301 0001 .t.e...e....3... 0006830: ff10 bb4f 10e8 f364 0002 ebf0 c08f ff2d ...O...d.......- 0006840: 000f 2902 2f0f eaf1 41ff 043f 0340 003e ..)./...A..?.@.> 0x0020 00 A8 00 00 -> 4th start 0x0024 9C 37 00 00 -> 4th size 000a800: b163 0000 ff09 0f06 0000 6008 00df 0900 .c........`..... 000a810: 0860 0af5 f009 60ff 1b00 4c00 5200 5300 .`....`...L.R.S. 000a820: ff70 1065 8001 0065 a0ff 0100 3301 0001 .p.e...e....3... 000a830: ff10 fb0a 10e8 f341 043f 0340 ff00 3e00 .......A.?.@..>. 000a840: 3b80 3c80 3bff 8039 033a 0038 000f ff00 ;.<.;..9.:.8.... 0x0028 00 E0 00 00 -> 5th start 0x002C 5A 53 00 00 -> 5th size 0x0030 00 38 01 00 -> 6th start </pre> 于是可以解出来 但是貌似多数文件都压缩了…… * ADX = Ogg * BIP: Many possible formats... * T2P: Image, ... Update: 其实都是标准的[[LZSS]]压缩,只是我原来不知道还有那么些恶心的地方,于是搞了好久…… 图片都是TIM2格式,据说是PS2的?里面包着奇怪的东西,多数是原封不动的PNG BIP有些是脚本,格式还不清楚,反正最后有字符串库,前面不知道是啥…… == 解包代码 == unlzss.cpp <source lang="cpp"> #include <iostream> #include <fcntl.h> #include <vector> #include <string> #include <sys/endian.h> #include <errno.h> #include <sys/stat.h> #include <zlib.h> using namespace std; typedef unsigned char uchar; string dump(unsigned char *data) { char buf[20]; snprintf(buf, 20, "%02x %02x %02x %02x", data[0], data[1], data[2], data[3]); return string(buf); } void toh(uint32_t &x) { x = le32toh(x); } class File { int size, offset; uchar sig1[4], sig2[4], mark[4], xx[4]; string name; public: File(int _offset, int _size) : size(_size), offset(_offset) {} int get_size() { return size; } int get_offset() { return offset; } const string & get_name() { return name; } void set_info(const string& _name, uchar *_sig1, uchar *_sig2, uchar *_mark, uchar *_xx) { name = _name; memcpy(sig1, _sig1, 4); memcpy(sig2, _sig1, 4); memcpy(mark, _mark, 4); memcpy(xx, _xx, 4); } }; int main(int argc, char **argv) { if (argc < 2) { cout << "usage: " << argv[0] << " <afs file> [<output dir>]" << endl; return -1; } char head[4]; int f = open(argv[1], O_RDONLY); if (f < 0) { cout << "fail to open file: " << errno << endl; return -2; } read(f, head, 4); if (memcmp(head, "AFS\0", 4) != 0) { cout << "signature mismatch!\n" << endl; close(f); return 1; } vector<File> files; uint32_t filecount; read(f, &filecount, 4); filecount = le32toh(filecount); cout << "file count: " << filecount << endl; // last file: directory for (int i=0; i<filecount+1; i++) { uint32_t offset, size; read(f, &offset, 4); read(f, &size, 4); toh(offset); toh(size); if ((size == 0) && (i == filecount)) { // ugly state: no last record int x = files[i-1].get_offset() + files[i-1].get_size() + 1; lseek(f, x, SEEK_SET); char ch; read(f, &ch, 1); while (ch == 0) { read(f, &ch, 1); x++; } offset = x; size = 0x30 * filecount; } files.push_back(File(offset, size)); // cout << "File " << i << ": offset=" << hex << files[i].get_offset() << ",size=" << size << "#" << dec << size << dec << endl; } for (int i=0; i<filecount; i++) { lseek(f, files[filecount].get_offset() + 0x30 * i, SEEK_SET); char name[33]; name[32] = '\0'; read(f, name, 32); string sname(name); unsigned char sig1[4]; unsigned char sig2[4]; read(f, sig1, 4); read(f, sig2, 4); unsigned char mark[4]; read(f, mark, 4); unsigned char xx[4]; read(f, xx, 4); files[i].set_info(sname, sig1, sig2, mark, xx); cout << "File " << i << ": name=" << sname << ",offset=" << hex << files[i].get_offset() << ",size=" << files[i].get_size() << dec << endl; cout << "sig1=" << dump(sig1) << ",sig2=" << dump(sig2) << ",mark=" << dump(mark) << ",mock=" << dump(xx) << endl; } if (argc > 2) { string destdir = argv[2]; mkdir(destdir.c_str(), 0755); int bufsize = 0; char *buf = NULL; char *unbuf = NULL; int unbufsize = 0; for (int i=0; i<filecount; i++) { File &frec = files[i]; lseek(f, frec.get_offset(), SEEK_SET); if (frec.get_size() > bufsize) { if (buf) delete []buf; buf = new char[frec.get_size()]; } int cnt = read(f, buf, frec.get_size()); if (cnt != frec.get_size()) { cerr << "warning: partial read for " << frec.get_name() << " " << cnt << " instead of " << frec.get_size() << " errno " << errno << endl; } string destpath = destdir + "/" + frec.get_name(); int outf = open(destpath.c_str(), O_WRONLY | O_CREAT, 0644); if (outf < 0) { cerr << "failed to open output file for " << destpath << " : " << errno << endl; } else { cout << "writing to " << destpath << " size: " << cnt << endl; write(outf, buf, cnt); close(outf); } } } } </source>
返回至
AFS file
。