FlashFSUnWiggler.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. package de.nplusc.izc.senabitwiggler;
  2. import com.google.common.primitives.Ints;
  3. import com.google.common.primitives.Shorts;
  4. import de.nplusc.izc.senabitwiggler.DataStructures.QualCommHeaderRecord;
  5. import de.nplusc.izc.senabitwiggler.DataStructures.QualCommWrapper;
  6. import org.apache.logging.log4j.LogManager;
  7. import org.apache.logging.log4j.Logger;
  8. import org.yaml.snakeyaml.Yaml;
  9. import java.io.*;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Random;
  13. public class FlashFSUnWiggler {
  14. private static final Logger l = LogManager.getLogger();
  15. private static class FileMetadata
  16. {
  17. private int offset;
  18. private boolean is_dir;
  19. private int length;
  20. private int offset_fname;
  21. private String filename;
  22. private String parentpath;
  23. }
  24. public static void unpackFSQCC512x(File firmware, File outfolder)
  25. {
  26. try (RandomAccessFile f = new RandomAccessFile(firmware,"r")) {
  27. byte[] javaisDipshit = new byte[4];
  28. byte[] javaShorty = new byte[2];
  29. int magic = f.readInt(); //ignored
  30. f.read(javaisDipshit);
  31. int sizeFile = Ints.fromBytes(javaisDipshit[3],javaisDipshit[2],javaisDipshit[1],javaisDipshit[0]);
  32. if(sizeFile>f.length())
  33. {
  34. l.info(sizeFile);
  35. l.info("ZOINKS!!!, mismatch");
  36. return;
  37. }
  38. f.read(javaisDipshit);
  39. int countFileRecords = Ints.fromBytes(javaisDipshit[3],javaisDipshit[2],javaisDipshit[1],javaisDipshit[0]);
  40. FileMetadata[] files = new FileMetadata[countFileRecords];
  41. for(int i=0;i<countFileRecords;i++)
  42. {
  43. FileMetadata fmd = new FileMetadata();
  44. f.read(javaisDipshit);
  45. int sizeAndFlags = Ints.fromBytes(javaisDipshit[3],javaisDipshit[2],javaisDipshit[1],javaisDipshit[0]);
  46. int size = sizeAndFlags&0x00FFFFFF;
  47. l.info(sizeAndFlags);
  48. l.info(size);
  49. fmd.offset_fname=size;
  50. if((sizeAndFlags&0xFF000000)<0)
  51. {
  52. l.info("dir");
  53. fmd.is_dir=true;
  54. }
  55. f.read(javaisDipshit);
  56. fmd.offset=Ints.fromBytes(javaisDipshit[3],javaisDipshit[2],javaisDipshit[1],javaisDipshit[0]);
  57. f.read(javaisDipshit);
  58. fmd.length=Ints.fromBytes(javaisDipshit[3],javaisDipshit[2],javaisDipshit[1],javaisDipshit[0]);
  59. files[i]=fmd;
  60. }
  61. for(int i=0;i<countFileRecords;i++)
  62. {
  63. FileMetadata fmd = files[i];
  64. if(fmd.offset_fname==0)
  65. {
  66. fmd.filename="";
  67. fmd.parentpath="";
  68. }
  69. else
  70. {
  71. f.seek(fmd.offset_fname);
  72. f.read(javaShorty);
  73. short fnlength = Shorts.fromBytes(javaShorty[1],javaShorty[0]);
  74. byte[] fname = new byte[fnlength];
  75. f.read(fname);
  76. String s = File.separator+new String(fname);
  77. fmd.filename=s;
  78. }
  79. if(fmd.is_dir)
  80. {
  81. new File(outfolder+fmd.parentpath+fmd.filename).mkdirs();
  82. for(int j= 0;j< fmd.length;j++)
  83. {
  84. int subfiles = fmd.offset+j-1;
  85. files[subfiles].parentpath=fmd.parentpath+fmd.filename;
  86. }
  87. }
  88. else
  89. {
  90. l.info("Reading:"+fmd.parentpath+fmd.filename+"("+fmd.length+")@"+fmd.offset);
  91. byte[] filecontent = new byte[fmd.length];
  92. if(fmd.length>0)
  93. {
  94. f.seek(fmd.offset);
  95. f.read(filecontent);
  96. RandomAccessFile out = new RandomAccessFile(outfolder+fmd.parentpath+fmd.filename,"rw");
  97. out.write(filecontent);
  98. }
  99. }
  100. }
  101. } catch (FileNotFoundException e) {
  102. e.printStackTrace();
  103. } catch (IOException e) {
  104. e.printStackTrace();
  105. }
  106. }
  107. public static void unpackCSRFS(File firmware, File outfolder)
  108. {
  109. try (RandomAccessFile f = new RandomAccessFile(firmware,"r")) {
  110. int filler = -1;
  111. byte[] fillershort = new byte[]{(byte)0xff,(byte)0xff};
  112. RandomAccessFile boobs = new RandomAccessFile(new File(outfolder,"debug.dat"),"rw");
  113. byte[] javaisDipshit = new byte[4];
  114. byte[] javaShorty = new byte[2];
  115. int magic = f.readInt(); //ignored
  116. f.read(javaisDipshit);
  117. boobs.write(filler);
  118. int sizeFile = Ints.fromBytes(javaisDipshit[0],javaisDipshit[1],javaisDipshit[2],javaisDipshit[3]);
  119. //old shit calculates in words and not in bytes on sizes
  120. if((sizeFile*2)>f.length())
  121. {
  122. l.info(sizeFile);
  123. l.info("ZOINKS!!!, mismatch");
  124. return;
  125. }
  126. byte[] background = new byte[(int)f.length()];
  127. for(int i=0;i<background.length;i++)
  128. {
  129. background[i]=0;
  130. }
  131. boobs.seek(0);
  132. boobs.write(background);
  133. boobs.seek(0);
  134. boobs.write(filler);
  135. boobs.write(filler);
  136. f.read(javaisDipshit);
  137. int countFileRecords = (Ints.fromBytes(javaisDipshit[2],javaisDipshit[3],javaisDipshit[0],javaisDipshit[1]) &0x00FFFFFF);
  138. l.info(countFileRecords);
  139. int countFileRecordsXXX = (Ints.fromBytes(javaisDipshit[1],javaisDipshit[0],javaisDipshit[3],javaisDipshit[2])&0x00FFFFFF);
  140. l.info(countFileRecordsXXX);
  141. boobs.write(fillershort);
  142. boobs.seek(10);
  143. f.seek(10);
  144. byte[] fakeFileRecord = new byte[12];
  145. for(int i=0;i<12;i++)
  146. {
  147. fakeFileRecord[i]=(byte)0xee;
  148. }
  149. FileMetadata[] files = new FileMetadata[countFileRecords];
  150. for(int i=0;i<countFileRecords;i++)
  151. {
  152. FileMetadata fmd = new FileMetadata();
  153. f.read(javaisDipshit);
  154. int sizeAndFlags = Ints.fromBytes(javaisDipshit[0],javaisDipshit[1],javaisDipshit[2],javaisDipshit[3]);
  155. int size = sizeAndFlags&0x00FFFFFF;
  156. l.info("SZFlg>>"+sizeAndFlags);
  157. l.info("SZExtr>>"+size);
  158. fmd.offset_fname=size;
  159. if((sizeAndFlags&0xFF000000)<0)
  160. {
  161. l.info("dir");
  162. fmd.is_dir=true;
  163. }
  164. f.read(javaisDipshit);
  165. fmd.offset=Ints.fromBytes(javaisDipshit[0],javaisDipshit[1],javaisDipshit[2],javaisDipshit[3]);
  166. f.read(javaisDipshit);
  167. fmd.length=Ints.fromBytes(javaisDipshit[0],javaisDipshit[1],javaisDipshit[2],javaisDipshit[3]);
  168. files[i]=fmd;
  169. boobs.write(fakeFileRecord);
  170. }
  171. for(int i=0;i<countFileRecords;i++)
  172. {
  173. FileMetadata fmd = files[i];
  174. if(fmd.offset_fname==0)
  175. {
  176. fmd.filename="";
  177. fmd.parentpath="";
  178. }
  179. else
  180. {
  181. f.seek(fmd.offset_fname*2); //words again...
  182. f.read(javaShorty);
  183. short fnlength = Shorts.fromBytes(javaShorty[0],javaShorty[1]);
  184. byte[] fname = new byte[fnlength*2];
  185. f.read(fname);
  186. byte[] fname_real = new byte[fnlength];
  187. for(int fi=0;fi<fname_real.length;fi++)
  188. {
  189. fname_real[fi]=fname[fi*2+1]; //zapping each upper bit...
  190. }
  191. for(int j=0;j<fname.length;j++)
  192. {
  193. fname[j]=(byte) 0xCC;
  194. }
  195. boobs.seek(fmd.offset_fname*2); //words again...
  196. boobs.write(new byte[]{(byte)0xDD,(byte)0xDD});
  197. boobs.write(fname);
  198. String s = File.separator+new String(fname_real);
  199. fmd.filename=s;
  200. }
  201. if(fmd.is_dir)
  202. {
  203. new File(outfolder+fmd.parentpath+fmd.filename).mkdirs();
  204. for(int j= 0;j< fmd.length;j++)
  205. {
  206. int subfiles = fmd.offset+j-1;
  207. if(subfiles==-1)
  208. {
  209. l.info("WTF?");
  210. }
  211. files[subfiles].parentpath=fmd.parentpath+fmd.filename;
  212. }
  213. }
  214. else
  215. {
  216. l.info("Reading:"+fmd.parentpath+fmd.filename+"("+fmd.length+")@"+fmd.offset);
  217. byte[] filecontent = new byte[fmd.length];
  218. if(fmd.length>0)
  219. {
  220. f.seek(fmd.offset*2);
  221. int readme = f.read(filecontent);
  222. RandomAccessFile out = new RandomAccessFile(outfolder+fmd.parentpath+fmd.filename,"rw");
  223. out.write(filecontent);
  224. if(readme<filecontent.length)
  225. {
  226. throw new IndexOutOfBoundsException("ZARF");
  227. }
  228. for(int k=0;k<filecontent.length;k++)
  229. {
  230. filecontent[k]=(byte)0xBB;
  231. }
  232. boobs.seek(fmd.offset*2);
  233. boobs.write(filecontent);
  234. }
  235. }
  236. }
  237. } catch (FileNotFoundException e) {
  238. e.printStackTrace();
  239. } catch (IOException e) {
  240. e.printStackTrace();
  241. }
  242. }
  243. public static void unpackQCC512DFU(File firmware, File outfolder)
  244. {
  245. QualCommWrapper w = new QualCommWrapper();
  246. l.info("0x00!");
  247. try (RandomAccessFile f = new RandomAccessFile(firmware,"r"))
  248. {
  249. outfolder.mkdirs();
  250. f.read(new byte[8]); //skip header
  251. int hdrsize = f.readInt();
  252. byte[] header = new byte[hdrsize];
  253. f.read(header);
  254. w.header=header;
  255. // 1346458196
  256. // 1145132097
  257. int i = 0;
  258. List<QualCommHeaderRecord> files = new ArrayList<>();
  259. while(true)
  260. {
  261. QualCommHeaderRecord r = new QualCommHeaderRecord();
  262. if(f.readInt() != 1346458196)
  263. {
  264. l.info("Zarf!");
  265. break; //end of file
  266. }
  267. if(f.readInt() != 1145132097)
  268. {
  269. l.info("Zarf2!");
  270. break; //end of file
  271. }
  272. int sizeData = f.readInt();
  273. r.size = sizeData;
  274. l.info("Reading" +sizeData);
  275. short location = f.readShort();
  276. short sublocation = f.readShort();
  277. r.location=location;
  278. r.sublocation=sublocation;
  279. String filename = location+"_"+sublocation+".dat";
  280. r.filename=filename;
  281. byte[] innerFile = new byte[sizeData-4];
  282. f.read(innerFile);
  283. RandomAccessFile fo = new RandomAccessFile(new File(outfolder,filename),"rw");
  284. fo.write(innerFile);
  285. fo.close();
  286. i++;
  287. files.add(r);
  288. }
  289. int bytesLeft = 4+((int)(f.length()-f.getFilePointer()));
  290. byte[] rest = new byte[bytesLeft];
  291. f.seek(f.getFilePointer()-4);
  292. f.read(rest);
  293. w.footer=rest;
  294. w.files = files.toArray(new QualCommHeaderRecord[files.size()]);
  295. Yaml y = new Yaml();
  296. y.dump(w, new FileWriter(new File(outfolder,"header.yml")));
  297. } catch (FileNotFoundException e) {
  298. e.printStackTrace();
  299. } catch (IOException e) {
  300. e.printStackTrace();
  301. }
  302. }
  303. public static void repackQualcommWrapper(File newfirmware, File inputfolder)
  304. {
  305. QualCommWrapper header;
  306. try {
  307. header = new Yaml().loadAs(new FileReader(new File(inputfolder,File.separator+"header.yml")),QualCommWrapper.class);
  308. } catch (FileNotFoundException e) {
  309. e.printStackTrace();
  310. return;
  311. }
  312. l.info("0x00!");
  313. if(newfirmware.exists())
  314. {
  315. l.error("Refusing to overwrite a existing file!!!");
  316. return;
  317. }
  318. try (RandomAccessFile f = new RandomAccessFile(newfirmware,"rw"))
  319. {
  320. f.writeInt(0x41505055);
  321. f.writeInt(0x48445232);
  322. f.writeInt(header.header.length);
  323. f.write(header.header);
  324. // 1346458196
  325. // 1145132097
  326. for(QualCommHeaderRecord r:header.files)
  327. {
  328. RandomAccessFile f2 = new RandomAccessFile(new File(inputfolder,r.filename),"r");
  329. int size = (int) f2.length();
  330. byte[] file = new byte[size];
  331. f2.read(file);
  332. f.writeInt(1346458196);
  333. f.writeInt(1145132097);
  334. f.writeInt(size+4);
  335. f.writeShort(r.location);
  336. f.writeShort(r.sublocation);
  337. f.write(file);
  338. f2.close();
  339. }
  340. f.write(header.footer);
  341. } catch (FileNotFoundException e) {
  342. e.printStackTrace();
  343. } catch (IOException e) {
  344. e.printStackTrace();
  345. }
  346. }
  347. }