Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ### no-js
- This challenge is a usual crackme, but implemented in javascript. First step is to find entry point and what is happening with entered input.
- ```javascript
- function Tk() {
- var a = dj.c(""),
- b = dj.c(!1),
- c = dj.c(!1),
- d = dj.c(!1);
- return function(a, b, c, d) {
- return function() {
- return new Y(null, 5, 5, Z, [yh, new Va(null, 1, [Gh, "container"], null), new Y(null, 3, 5, Z, [yh, new Va(null, 1, [Gh, ["background ", D.c(y(I(c)) ? "background-b" : "background-a")].join("")], null), new Y(null, 2, 5, Z, [Zh, new Va(null, 1, [sh, ["images/", D.c(y(I(c)) ? "FGKG09C" : "FGKG09B"), ".jpg"].join("")], null)], null)], null), new Y(null, 4, 5, Z, [yh, new Va(null, 1, [Gh, "absolute-center"], null), Ya(function() {
- var a = I(c);
- return y(a) ?
- a : I(b)
- }()) ? new Y(null, 4, 5, Z, [bh, Kk, new Va(null, 2, [Yh, function(a, b) {
- return function() {
- return Ke(b, !0)
- }
- }(a, b, c, d), mh, !0], null), "Enter Password"], null) : null, y(I(c)) ? new Y(null, 4, 5, Z, [yh, new Va(null, 1, [xh, new Va(null, 4, [Yg, "white", Ph, "3em", Kh, "center", ah, "0px 2px 15px green"], null)], null), new Y(null, 2, 5, Z, [Vh, "Flag correct!"], null), new Y(null, 2, 5, Z, [Vh, ["RCTF{", D.c(I(a)), "}"].join("")], null)], null) : null], null), y(function() {
- var a = I(b);
- return y(a) ? Ya(I(c)) : a
- }()) ? new Y(null, 6, 5, Z, [bh, Mk, new Va(null, 2, [zh,
- "blurring", Sg, I(b)
- ], null), new Y(null, 3, 5, Z, [bh, Ok, "Input"], null), new Y(null, 4, 5, Z, [bh, Pk, y(I(d)) ? Ya(I(c)) ? new Y(null, 3, 5, Z, [Vh, new Va(null, 1, [xh, new Va(null, 2, [Yg, "red", Kh, "center"], null)], null), "Flag incorrect"], null) : null : null, new Y(null, 2, 5, Z, [Sk, a], null)], null), new Y(null, 3, 5, Z, [bh, Qk, new Y(null, 4, 5, Z, [bh, Kk, new Va(null, 2, [Yh, function(a, b, c, d) {
- return function() {
- y(Rk(I(a))) && Ke(c, !0);
- Ke(d, !0);
- return setTimeout(function(a, b, c, d) {
- return function() {
- return Ke(d, !1)
- }
- }(a, b, c, d), 5E3)
- }
- }(a, b, c, d), mh, !0],
- null), "Verify"], null)], null)], null) : null], null)
- }
- }(a, b, c, d)
- }
- ```
- In this part of code "Flag is correct/incorrect" strings are exposed and expected flag format: `["RCTF{", D.c(I(a)), "}"]`. In function `Rk` we can spot our input string:
- ```javascript
- function Rk(a) {
- rg = gi(a, "_");
- // if (K.f(S(rg), S(sg))) {
- // return K.f(S(Se(Fd, Re(function(a) { return we(yb(a), new Y(null, 1, 5, Z, [xb(a)], null)) }, qg()))), S(sg));
- // }
- return K.f(S(rg), S(sg)) ? K.f(S(Se(Fd, Re(function(a) {
- return we(yb(a), new Y(null, 1, 5, Z, [xb(a)], null))
- }, qg()))), S(sg)) : !1
- }
- ```
- which is later split by underscores and object `rg` is formed from it and number of splitted parts is compared to number of elements in `sg.pa` field. Thus we can learn that flag is looking like `A_B_C_D_E_F_G`. By placing breakpoints inside of fuctions of `sg.pa` array we can find that splitted parts of input are correspondingly checked by functions from that array, so we can expect that to successfully recover the flag we need to pass all 7 checks in that object.
- ### Part A
- ```javascript
- var sg = new Y(null, 7, 5, Z, [function(a) {
- return K.f(a, "no")
- }
- ```
- It is a simple check `a === "no"`, so first part of flag is "no".
- ### Part B
- ```javascript
- function(a) {
- return K.f(0, Kd(new Y(null, 10, 5, Z, [45, 36, 57, 36, 54, 38, 53, 1, 51, 55], null), li(a)))
- }
- ```
- It is a check that `li(a) === [45, 36, 57, 36, 54, 38, 53, 1, 51, 55]`. `li` is a simple function mapping symbols in the following way:
- ```javascript
- function li(a) {
- return Re(function(a) {
- a = a.charCodeAt();
- return 57 >= a ? a - 48 : 90 >= a ? a - 65 + 10 : 122 >= a ? a - 97 + 36 : null
- }, a.split(""))
- }
- ```
- So we can recover symbols back from given array, second part of the flag is `javascr1pt`.
- ### Parts C and D
- ```javascript
- function(a) {
- return K.f(mi(a), "0SWCRMLH")
- }, function(a) {
- return K.f(mi(a), "000EQTPI")
- }
- ```
- This checks are calculating some kind of hash from input string and compares it to given values. At first step seven numbers are calculated from input string, (`J.f(ki, 5 * a)` is a first element of input string, `J.f(ki, 5 * a + 1)` - second and so on):
- ```javascript
- var first = J.f(ki, 5 * a) >> 3;
- var second = Fc(
- [
- (J.f(ki, 5 * a) & 7) << 2 | J.f(ki, 5 * a + 1) >> 6,
- (J.f(ki, 5 * a + 1) & 63) >> 1,
- (J.f(ki, 5 * a + 1) & 1) << 4 | J.f(ki, 5 * a + 2) >> 4,
- (J.f(ki, 5 * a + 2) & 15) << 1 | J.f(ki, 5 * a + 3) >> 7,
- (J.f(ki, 5 * a + 3) & 127) >> 2,
- (J.f(ki, 5 * a + 3) & 3) << 3 | J.f(ki, 5 * a + 4) >> 5,
- J.f(ki, 5 * a + 4) & 31
- ]
- );
- ```
- At the second step those numbers are used as indicies in alphabet string "765432ABCDEFGHIJKLMNOPQRSTUVWXYZ", resulting is padded with zeroes and then reversed. Padding:
- ```javascript
- ji = K.f(c, 1) ? 6 : K.f(c, 2) ? 4 : K.f(c, 3) ? 3 : K.f(c, 4) ? 1 : 0;
- ```
- `K.f(c, 1) === (c, n) => { c.length === n }` - true if length of input string is 1. So for 3 zeroes in pad input must have length of 3 and for 1 zero length of 4. By reversing strings "0SWCRMLH" and "000EQTPI" to indices in alphabet and reversing all bitwise operations from aforementioned formulas we can learn next two parts of flag - "lets" and "use".
- ### Part E
- ```javascript
- function Bk(a) {
- var j=window['BigInt'],w=j['asIntN'];
- var first = w(256,"276839132707622690534147184366986393054208");
- var second = D.c(fi(",", Ak(a, Vg))).split(',');
- var third = second.map(j).reduce((a, b)=>a*256n+b)<<10n;
- return first === third;
- }
- function Ak(a) {
- for (var b = [], c = arguments.length, d = 0;;)
- if (d < c) b.push(arguments[d]), d += 1;
- else break;
- c = arguments[0];
- d = arguments[1];
- b = ld(2 < b.length ? new M(b.slice(2), 0, null) : null, 0);
- a: switch (d = d instanceof v ? d.Ia : null, d) {
- case "md5":
- var e = new yk;
- break a;
- default:
- throw Error(["No matching clause: ", D.c(d)].join(""));
- }
- d = [];
- for (var f = 0, g = 0; g < c.length; g++) {
- var k = c.charCodeAt(g);
- 128 > k ? d[f++] = k : (2048 > k ? d[f++] = k >> 6 | 192 : (55296 == (k & 64512) && g + 1 < c.length && 56320 == (c.charCodeAt(g + 1) & 64512) ? (k = 65536 + ((k & 1023) << 10) + (c.charCodeAt(++g) &
- 1023), d[f++] = k >> 18 | 240, d[f++] = k >> 12 & 63 | 128) : d[f++] = k >> 12 | 224, d[f++] = k >> 6 & 63 | 128), d[f++] = k & 63 | 128)
- }
- c = e;
- c.update(d);
- c = c.digest();
- return y(b) ? wk(c) : c
- }
- ```
- Function `Ak` calculates md5-hash from input string, which is later multiplied by 1024 and compared to some value in function `Bk`. By dividing it we can learn what is desired value of md5: cb63a762f1571806222efef7ec7f9c1b and then google this value. Next part of flag is "50me".
- ### Part F
- At first step input characters are split by pairs and converted into objects:
- ```javascript
- oi = ti(He.f(vg(function(a) {
- return ze(a, 12)
- }), ug()));
- Re(function(a) {
- return Sd(oi, a)
- }, li(a));
- ```
- At second step some function from these objects will be compared to predefined values:
- ```javascript
- return K.f(Kd(new Y(null, 6, 5, Z, [21104, 50328, 78128, 119488, 411168, 592832], null), function() {
- ```
- By placing breakpoint inside `Kd` function we can learn what are values that being compared, if we pass string "111111111111" as input: `[514, 1028, 2056, 4112, 8224, 16448, 32896]`. Using that internal formula can be guessed: `(li(first) * 512 + li(second)) * 2 ** (index)`, by computing values backwards for given numbers next part of flag is recovered: "funcccTional".
- ### Part G
- Last part of the flag is checked by comparing some function of input value with given base64-encoded string `"PVw6U2ZmYV1hRVAyUS9IW1t..."`. By passing different input string we can learn that each symbol of input string produces 11 symbols in output string and those symbols are "predefined". Resulting symbols are produced with the following code:
- ```javascript
- ed(c + g, w(Hc(a)))
- ```
- each symbol in input is summed with 11 symbols in linked list which is produced by
- ```javascript
- xe(hd, xe(hd, be(22, 33), li("okotta")), new Y(null, 3, 5, Z, [11, 45, 14], null))
- ```
- First value in that list is 14, so we can subtract 14 from first symbol in each block of 11 symbols in base64 decoded string `"PVw6U2ZmYV1hRVAyUS9IW1t..."` and recover last part of the flag: "laaaannGuageeee1".
- ### Flag
- RCTF{no_javascr1pt_lets_use_50me_funcccTional_laaaannGuageeee1}
Add Comment
Please, Sign In to add comment