Sleazy Fork is available in English.

wasm parsere

used to modify wasm

Bu script direkt olarak kurulamaz. Başka scriptler için bir kütüphanedir ve meta yönergeleri içerir // @require https://update.sleazyfork.org/scripts/456876/1130174/wasm%20parsere.js

  1. // ==UserScript==
  2. // @name wasm parsere
  3. // @version 1.0
  4. // @description used to modify wasm
  5. // @author bismuth k
  6. // ==/UserScript==
  7. const OP = {"unreachable":0,"nop":1,"block":2,"loop":3,"if":4,"else":5,"end":11,"br":12,"br_if":13,"br_table":13,"return":15,"call":16,"call_indirect":17,"drop":26,"select":27,"local":{"get":32,"set":33,"tee":34},"global":{"get":35,"set":36},"i32":{"load":40,"load8_s":44,"load8_u":45,"load16_s":46,"load16_u":47,"store":54,"store8":58,"store16":59,"const":65,"eqz":69,"eq":70,"ne":71,"lt_s":72,"lt_u":73,"gt_s":74,"gt_u":75,"le_s":76,"le_u":77,"ge_s":78,"ge_u":79,"clz":103,"ctz":104,"popcnt":105,"add":106,"sub":107,"mul":108,"div_s":109,"div_u":110,"rem_s":111,"rem_u":112,"and":113,"or":114,"xor":115,"shl":116,"shr_s":117,"shr_u":118,"rotl":119,"rotr":120,"wrap_i64":167,"wrap_f32_s":168,"wrap_f32_u":169,"wrap_f64_s":170,"wrap_f64_u":171,"reinterpret_f32":188},"i64":{"load":41,"load8_s":48,"load8_u":49,"load16_s":50,"load16_u":51,"load32_s":52,"load32_u":53,"store":55,"store8":60,"store16":61,"store32":62,"const":66,"eqz":80,"eq":81,"ne":82,"lt_s":83,"lt_u":84,"gt_s":85,"gt_u":86,"le_s":87,"le_u":88,"ge_s":89,"ge_u":90,"clz":121,"ctz":122,"popcnt":123,"add":124,"sub":125,"mul":126,"div_s":127,"div_u":128,"rem_s":129,"rem_u":130,"and":131,"or":132,"xor":133,"shl":134,"shr_s":135,"shr_u":136,"rotl":137,"rotr":138,"extend_i32_s":172,"extend_i32_u":173,"trunc_f32_s":174,"trunc_f32_u":175,"trunc_f64_s":176,"trunc_f64_u":177,"reinterpret_f64":189},"f32":{"load":42,"store":56,"const":67,"eq":75,"ne":76,"lt":77,"gt":78,"le":79,"ge":80,"abd":139,"neg":140,"ceil":141,"floor":142,"trunc":143,"nearest":144,"sqrt":145,"add":146,"sub":147,"mul":148,"div":149,"min":150,"max":151,"copysign":152,"convert_i32_s":178,"convert_i32_u":179,"convert_i64_s":180,"convert_i64_u":181,"demote_f64":182,"reinterpret_i32":190},"f64":{"load":43,"store":57,"const":68,"eq":97,"ne":98,"lt":99,"gt":100,"le":101,"ge":102,"abd":153,"neg":154,"ceil":155,"floor":156,"trunc":157,"nearest":158,"sqrt":159,"add":160,"sub":161,"mul":162,"div":163,"min":164,"max":165,"copysign":166,"convert_i32_s":183,"convert_i32_u":184,"convert_i64_s":185,"convert_i64_u":186,"promote_f32":187,"reinterpret_i64":191},"memory":{"size":63,"grow":64}};
  8. class WASMSection {
  9. constructor(desc,length) {
  10. this.section = desc;
  11. this.body = new Array(length);
  12. }
  13. }
  14. class WASMParser {
  15. constructor(bin) {
  16. this.lexer = new Reader(new Uint8Array(bin));
  17. this.sections = new Array(13);
  18. this.adjustImports = 0;
  19. this.importFuncCount = 0;
  20. this.parseWASM();
  21. }
  22. read(bin) { this.lexer.packet = new Uint8Array(bin) }
  23. regex(match, allOccurences) {
  24. let ret = [], rets = [];
  25. search: for (let n = this.lexer.index; n < this.lexer.packet.length - match.length; n++) {
  26. this.lexer.index = n;
  27. ret = [];
  28. for (let p = 0; p < match.length; p++) {
  29. if (match[p] === '*') this.lexer.vu();
  30. else if (match[p] === '+') ret.push(this.lexer.vu());
  31. else if (this.lexer.u8() !== match[p]) continue search;
  32. }
  33. if (allOccurences) rets.push(ret);
  34. else {
  35. this.lexer.index = n;
  36. return ret;
  37. }
  38. }
  39. return rets.length? rets: false;
  40. }
  41. loadFunc(index) {
  42. this.lexer.set(this.sections[10].body[index - this.importFuncCount]);
  43. const localLength = this.lexer.vu();
  44. for (let n = 0; n < localLength; n++) {
  45. this.lexer.vu();
  46. this.lexer.u8();
  47. }
  48. return;
  49. }
  50. set(index, val) {
  51. this.sections[10].body[index - this.importFuncCount] = val;
  52. }
  53. getAdjusted(index) {
  54. if (index < this.importFuncCount) return index;
  55. return index + this.adjustImports;
  56. }
  57. addImportEntry(options) {
  58. const map = ['f64','f32','i64','i32'];
  59. switch(options.type) {
  60. case 'func':
  61. this.sections[2].body.push({
  62. name: options.name,
  63. type: "func",
  64. index: this.sections[1].body.length
  65. });
  66. this.sections[1].body.push({
  67. param: options.params,
  68. return: options.returns
  69. });
  70. this.adjustImports++;
  71. return this.sections[2].body.length - 1;
  72. break;
  73. default:
  74. throw new Error('oops, not supported yet');
  75. break;
  76. }
  77. }
  78. reindex() {
  79. let section = this.sections[10].body;
  80. let length = section.length;
  81. for (let n = 0; n < length; n++) this.sections[10].body[n] = this.parseFunction(section[n]);
  82. section = this.sections[9].body;
  83. length = section.length;
  84. for (let n = 0; n < length; n++) {
  85. const l = section[n].funcs.length;
  86. for (let p = 0; p < l; p++) this.sections[9].body[n].funcs[p] = this.getAdjusted(section[n].funcs[p]);
  87. }
  88. section = this.sections[7].body;
  89. length = section.length;
  90. for (let n = 0; n < length; n++) this.sections[7].body[n].index = this.getAdjusted(section[n].index);
  91. this.adjustImports = 0;
  92. }
  93. compile() {
  94. const bin = [0, 97, 115, 109, 1, 0, 0, 0];
  95. for (let n = 0; n < 12; n++) {
  96. if (!this.sections[n]) continue;
  97. const section = this[`compileSection0x${n.toString(16)}`]();
  98. bin.push(n);
  99. bin.push(...Writer.vu(section.length));
  100. for (const byte of section) bin.push(byte);
  101. }
  102. return new Uint8Array(bin);
  103. }
  104. compileSection0x1() {
  105. const map = ['f64','f32','i64','i32'];
  106. const section = this.sections[1].body;
  107. const length = section.length;
  108. const bin = Writer.vu(length);
  109. for (let n = 0; n < length; n++) {
  110. bin.push(0x60);
  111. bin.push(...Writer.vu(section[n].param.length));
  112. for (const param of section[n].param) bin.push(map.indexOf(param) + 0x7C);
  113. bin.push(...Writer.vu(section[n].return.length));
  114. for (const param of section[n].return) bin.push(map.indexOf(param) + 0x7C);
  115. }
  116. return bin;
  117. }
  118. compileSection0x2() {
  119. const map = ['func','table','mem','global'];
  120. const section = this.sections[2].body;
  121. const length = section.length;
  122. const bin = Writer.vu(length);
  123. for (let n = 0; n < length; n++) {
  124. const nameSplit = section[n].name.split('.');
  125. for (const part of nameSplit) bin.push(...Writer.stringLEN(part));
  126. bin.push(map.indexOf(section[n].type));
  127. bin.push(...Writer.vu(section[n].index));
  128. //console.log(bin);
  129. }
  130. return bin;
  131. }
  132. compileSection0x3() {
  133. const section = this.sections[3].body;
  134. const length = section.length;
  135. const bin = Writer.vu(length);
  136. for (let n = 0; n < length; n++) bin.push(...Writer.vu(section[n]));
  137. return bin;
  138. }
  139. compileSection0x4() {
  140. const section = this.sections[4].body;
  141. const length = section.length;
  142. const bin = Writer.vu(length);
  143. for (let n = 0; n < length; n++) for (let p = 0; p < 4; p++) bin.push(...Writer.vu(section[n][p]));
  144. return bin;
  145. }
  146. compileSection0x5() {
  147. const section = this.sections[5].body;
  148. const length = section.length;
  149. const bin = Writer.vu(length);
  150. for (let n = 0; n < length; n++) {
  151. bin.push(...Writer.vu(section[n].type));
  152. bin.push(...Writer.vu(section[n].limit[0]));
  153. bin.push(...Writer.vu(section[n].limit[1]));
  154. }
  155. return bin;
  156. }
  157. compileSection0x6() {
  158. const map = ['f64','f32','i64','i32'];
  159. const section = this.sections[6].body;
  160. const length = section.length;
  161. const bin = Writer.vu(length);
  162. for (let n = 0; n < length; n++) {
  163. bin.push(map.indexOf(section[n].type) + 0x7C);
  164. bin.push(section[n].mutable);
  165. for (const expr of section[n].expr) bin.push(...Writer.vu(expr));
  166. bin.push(11);
  167. }
  168. return bin;
  169. }
  170. compileSection0x7() {
  171. const map = ['func','table','mem','global'];
  172. const section = this.sections[7].body;
  173. const length = section.length;
  174. const bin = Writer.vu(length);
  175. for (let n = 0; n < length; n++) {
  176. bin.push(...Writer.stringLEN(section[n].name));
  177. bin.push(map.indexOf(section[n].type));
  178. bin.push(...Writer.vu(section[n].index));
  179. }
  180. return bin;
  181. }
  182. compileSection0x8() {
  183. const section = this.sections[8].body;
  184. const length = 1;
  185. const bin = [1];
  186. bin.push(...Writer.vu(section));
  187. return bin;
  188. }
  189. compileSection0x9() {
  190. const section = this.sections[9].body;
  191. const length = section.length;
  192. const bin = Writer.vu(length);
  193. for (let n = 0; n < length; n++) {
  194. bin.push(section[n].type, section[n].expr[0]);
  195. bin.push(...Writer.vi(section[n].expr[1]),11);
  196. bin.push(...Writer.vu(section[n].funcs.length));
  197. for (const funcIdx of section[n].funcs) bin.push(...Writer.vu(funcIdx));
  198. }
  199. return bin;
  200. }
  201. compileSection0xa() {
  202. const section = this.sections[10].body;
  203. const length = section.length;
  204. const bin = Writer.vu(length);
  205. for (let n = 0; n < length; n++) {
  206. //section[n] = this.parseFunction(section[n]);
  207. bin.push(...Writer.vu(section[n].length));
  208. for (const byte of section[n]) bin.push(byte);
  209. }
  210. return bin;
  211. }
  212. compileSection0xb() {
  213. const section = this.sections[11].body;
  214. const length = section.length;
  215. const bin = Writer.vu(length);
  216. for (let n = 0; n < length; n++) {
  217. bin.push(section[n].type,section[n].expr[0]);
  218. bin.push(...Writer.vi(section[n].expr[1]),11);
  219. bin.push(...Writer.vu(section[n].contents.length));
  220. bin.push(...section[n].contents);
  221. }
  222. return bin;
  223. }
  224. parseWASM() {
  225. this.lexer.index = 8;
  226. while (this.lexer.has()) {
  227. const id = this.lexer.u8();
  228. if (id > 12) return;
  229. this[`parseSection0x${id.toString(16)}`]();
  230. }
  231. this.importFuncCount = this.sections[2].body.filter(({type}) => type === 'func').length;
  232. }
  233. parseSection0x1() {
  234. const map = ['f64','f32','i64','i32'];
  235. const rawLength = this.lexer.vu();
  236. const section = new WASMSection('functypes', this.lexer.vu());
  237. for (let n = 0; n < section.body.length; n++) {
  238. const type = { param: [], return: [] }
  239. if (this.lexer.u8() !== 0x60) break;
  240. let len = this.lexer.vu();
  241. for (let n = 0; n < len; n++) type.param.push(map[this.lexer.u8()-0x7C]);
  242. len = this.lexer.vu();
  243. for (let n = 0; n < len; n++) type.return.push(map[this.lexer.u8()-0x7C]);
  244. section.body[n] = type;
  245. }
  246. return (this.sections[1] = section);
  247. }
  248. parseSection0x2() {
  249. const map = ['func','table','mem','global'];
  250. this.lexer.vu();
  251. const section = new WASMSection('imports', this.lexer.vu());
  252. for (let n = 0; n < section.body.length; n++) section.body[n] = { name: this.lexer.stringLEN() + '.' + this.lexer.stringLEN(), type: map[this.lexer.u8()], index: this.lexer.vu() };
  253. return (this.sections[2] = section);
  254. }
  255. parseSection0x3() {
  256. this.lexer.vu();
  257. const section = new WASMSection('functions', this.lexer.vu());
  258. for (let n = 0; n < section.body.length; n++) section.body[n] = this.lexer.vu();
  259. return (this.sections[3] = section);
  260. }
  261. parseSection0x4() {
  262. this.lexer.vu();
  263. const section = new WASMSection('tables', this.lexer.vu());
  264. for (let n = 0; n < section.body.length; n++) section.body[n] = [this.lexer.vu(), this.lexer.vu(), this.lexer.vu(), this.lexer.vu()]; //incomplete
  265. return (this.sections[4] = section);
  266. }
  267. parseSection0x5() {
  268. this.lexer.vu();
  269. const section = new WASMSection('mem', this.lexer.vu());
  270. for (let n = 0; n < section.body.length; n++) section.body[n] = { type: this.lexer.vu(), limit: [this.lexer.vu(), this.lexer.vu()] }
  271. return (this.sections[5] = section);
  272. }
  273. parseSection0x6() {
  274. const map = ['f64','f32','i64','i32'];
  275. this.lexer.vu();
  276. const section = new WASMSection('globals', this.lexer.vu());
  277. for (let n = 0; n < section.body.length; n++) {
  278. section.body[n] = { type: map[this.lexer.u8()-0x7C], mutable: this.lexer.u8(), expr: [] }
  279. section.body[n].expr.push(this.lexer.ru8());
  280. switch(this.lexer.u8()) {
  281. case OP.i32.const:
  282. case OP.i64.const:
  283. section.body[n].expr.push(this.lexer.vu());
  284. break;
  285. case OP.f32.const:
  286. section.body[n].expr.push(this.f32());
  287. break;
  288. case OP.f64.const:
  289. section.body[n].expr.push(this.f64());
  290. break;
  291. }
  292. this.lexer.u8();
  293. }
  294. return (this.sections[6] = section);
  295. }
  296. parseSection0x7() {
  297. const map = ['func','table','mem','global'];
  298. this.lexer.vu();
  299. const section = new WASMSection('exports', this.lexer.vu());
  300. for (let n = 0; n < section.body.length; n++) {
  301. const name = this.lexer.stringLEN();
  302. const type = map[this.lexer.u8()];
  303. const index = this.lexer.vu();
  304. section.body[n] = { name, type, index };
  305. }
  306. return (this.sections[7] = section);
  307. }
  308. parseSection0x8() {
  309. this.lexer.vu();
  310. const section = new WASMSection('start', this.lexer.vu());
  311. section.body = this.vu();
  312. return (this.sections[8] = section);
  313. }
  314. parseSection0x9() {
  315. this.lexer.vu();
  316. const section = new WASMSection('elements', this.lexer.vu());
  317. for (let n = 0; n < section.body.length; n++) {
  318. section.body[n] = { type: this.lexer.u8() }; //NEED TO ACCOUNT FOR DIFFERENT TYPES
  319. section.body[n].expr = [this.lexer.u8(),this.lexer.vu()];
  320. this.lexer.u8();
  321. const repeat = this.lexer.vu();
  322. section.body[n].funcs = [];
  323. for (let p = 0; p < repeat; p++) section.body[n].funcs.push(this.lexer.vu());
  324. }
  325. return (this.sections[9] = section);
  326. }
  327. parseSection0xa() {
  328. this.lexer.vu();
  329. const section = new WASMSection('code', this.lexer.vu());
  330. for (let n = 0; n < section.body.length; n++) {
  331. const len = this.lexer.vu();
  332. section.body[n] = this.lexer.packet.slice(this.lexer.index, this.lexer.index += len);
  333. }
  334. return (this.sections[10] = section);
  335. }
  336. parseSection0xb() {
  337. this.lexer.vu();
  338. const t = this.lexer.index;
  339.  
  340. const section = new WASMSection('data', this.lexer.vu());
  341. for (let n = 0; n < section.body.length; n++) {
  342. section.body[n] = { type: this.lexer.u8(), expr: [this.lexer.u8(),this.lexer.vu()] };
  343. this.lexer.u8();
  344. const len = this.lexer.vu();
  345. section.body[n].contents = this.lexer.packet.slice(this.lexer.index, this.lexer.index += len);
  346. }
  347. return (this.sections[11] = section);
  348. }
  349. parseFunction(func) {
  350. this.lexer.set(func);
  351. const localLength = this.lexer.vu();
  352. let len, before;
  353. for (let n = 0; n < localLength; n++) {
  354. this.lexer.vu();
  355. this.lexer.u8();
  356. }
  357. while(this.lexer.has()) {
  358. let op;
  359. switch(op = this.lexer.u8()) {
  360. case OP.block: case OP.loop: case OP.if:
  361. case OP.memory.size: case OP.memory.grow:
  362. this.lexer.u8();
  363. break;
  364. case OP.br: case OP.br_if:
  365. case OP.local.get: case OP.local.set: case OP.local.tee:
  366. case OP.i32.const: case OP.i64.const:
  367. this.lexer.vu();
  368. break;
  369. case OP.f32.const:
  370. this.lexer.f32();
  371. break;
  372. case OP.f64.const:
  373. this.lexer.f64();
  374. break;
  375. case OP.global.get: case OP.global.set:
  376. this.lexer.vu();
  377. break; //adjust global index later
  378. case OP.i32.load: case OP.i32.load8_s: case OP.i32.load8_u: case OP.i32.load16_s: case OP.i32.load16_u:
  379. case OP.i64.load: case OP.i64.load8_s: case OP.i64.load8_u: case OP.i64.load16_s: case OP.i64.load16_u: case OP.i64.load32_s: case OP.i64.load32_u:
  380. case OP.f32.load:
  381. case OP.f64.load:
  382. case OP.i32.store: case OP.i32.store8: case OP.i32.store16:
  383. case OP.i64.store: case OP.i64.store8: case OP.i64.store16: case OP.i64.store32:
  384. case OP.f32.store:
  385. case OP.f64.store:
  386. this.lexer.vu();
  387. this.lexer.vu();
  388. break;
  389. case OP.call_indirect:
  390. this.lexer.vu();
  391. this.lexer.u8();
  392. break;
  393. case OP.br_table:
  394. len = this.lexer.vu();
  395. for (let n = 0; n < len+1; n++) this.lexer.vu();
  396. break;
  397. case OP.call:
  398. len = this.lexer.index;
  399. before = this.lexer.vu();
  400. this.lexer.index = len;
  401. this.lexer.replaceVu(this.getAdjusted(before));
  402. break;
  403. default:
  404. if (op > 255) throw new Error('oops, you did something wrong');
  405. break;
  406. }
  407. }
  408. return this.lexer.packet;
  409. }
  410. }
  411. class Writer {
  412. static vu(num) {
  413. const ret = [];
  414. while (num >= 128) {
  415. ret.push((num & 127) | 128);
  416. num >>= 7;
  417. }
  418. ret.push(num);
  419. return ret;
  420. }
  421. static vi(num) {
  422. const ret = [];
  423. while (num >= 128) {
  424. ret.push((num & 127) | 128);
  425. num >>= 7;
  426. }
  427. if(num < 0x40) ret.push(num);
  428. else {
  429. ret.push(num | 0x80);
  430. ret.push(num<0?1:0);
  431. }
  432. return ret;
  433. }
  434. static stringLEN(str) {
  435. str = new TextEncoder().encode(str);
  436. if (str.length > 127) throw new Error('Unsupported string length: don\'t use a string that long (max 127 byte length)');
  437. return [str.length, ...str];
  438. }
  439. }
  440. class Reader {
  441. constructor(packet) {
  442. this.packet = packet;
  443. this.index = 0;
  444. const buffer = new ArrayBuffer(8);
  445. this._u8 = new Uint8Array(buffer);
  446. this._f32 = new Float32Array(buffer);
  447. this._f64 = new Float64Array(buffer);
  448. }
  449. inject(code) {
  450. const newBuf = new Uint8Array(code.length + this.packet.length);
  451. newBuf.set(this.packet.slice(0,this.index),0);
  452. newBuf.set(code,this.index);
  453. newBuf.set(this.packet.slice(this.index),(this.index+code.length));
  454. return (this.packet = newBuf);
  455. }
  456. replaceVu(replace) {
  457. const before = this.index, old = this.vu(), now = this.index;
  458. replace = Writer.vu(replace);
  459. if (replace.length === now - before) this.packet.set(replace, before);
  460. else {
  461. const newBuf = new Uint8Array(this.packet.length-now+before+replace.length);
  462. newBuf.set(this.packet.slice(0,before),0);
  463. newBuf.set(replace,before);
  464. newBuf.set(this.packet.slice(now),(this.index=before+replace.length));
  465. this.packet = newBuf;
  466. }
  467. }
  468. has() { return this.index < this.packet.length }
  469. set(packet) {
  470. this.packet = packet;
  471. this.index = 0;
  472. }
  473. ru8() { return this.packet[this.index] }
  474. u8() { return this.packet[this.index++] }
  475. f32() {
  476. this._u8.set(this.packet.slice(this.index, this.index += 4));
  477. return this._f32[0];
  478. }
  479. f64() {
  480. this._u8.set(this.packet.slice(this.index, this.index += 8));
  481. return this._f64[0];
  482. }
  483. vu() {
  484. let out = 0, at = 0;
  485. while (this.packet[this.index] & 0x80) {
  486. out |= (this.u8() & 0x7f) << at;
  487. at += 7;
  488. }
  489. out |= this.u8() << at;
  490. return out;
  491. }
  492. stringLEN() {
  493. const len = this.u8();
  494. const ret = new TextDecoder().decode(this.packet.slice(this.index, this.index += len));
  495. return ret;
  496. }
  497. }