1

I'm reverse engineering a javascript script to PHP and there are many functions that convert:

6 array bytes of [224, 221, 199, 147, 195, 47]

and output that to 1632933900000 (which is timestamp, Int64)

Can you help me how to pack/unpack those bytes as above to the final integer using PHP ?

Samples:

[224, 221, 199, 147, 195, 47] gets to 1632933900000

[224, 143, 228, 137, 198, 47] gets to 1633718700000

ADDITIONAL INFO:

The javascript code is very long (it was obfuscated). I just know for certain that it is placed within 6 bytes.

enter image description here

NEXT UPDATE...

It goes to this function (this.buf is array-bytes):

function u() {
    var e = new a(0, 0),
        t = 0;
    if (!(this.len - this.pos > 4)) {
        for (; t < 3; ++t) {
            if (this.pos >= this.len) throw s(this);
            if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 7 * t) >>> 0, this.buf[this.pos++] < 128) return e
        }
        return e.lo = (e.lo | (127 & this.buf[this.pos++]) << 7 * t) >>> 0, e
    }
    for (; t < 4; ++t)
        if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 7 * t) >>> 0, this.buf[this.pos++] < 128) return e;
    if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 28) >>> 0, e.hi = (e.hi | (127 & this.buf[this.pos]) >> 4) >>> 0, this.buf[this.pos++] < 128) return e;
    if (t = 0, this.len - this.pos > 4) {
        for (; t < 5; ++t)
            if (e.hi = (e.hi | (127 & this.buf[this.pos]) << 7 * t + 3) >>> 0, this.buf[this.pos++] < 128) return e
    } else
        for (; t < 5; ++t) {
            if (this.pos >= this.len) throw s(this);
            if (e.hi = (e.hi | (127 & this.buf[this.pos]) << 7 * t + 3) >>> 0, this.buf[this.pos++] < 128) return e
        }
    throw Error("invalid varint encoding")
}

And then it has [hi and low] numbers and this gets the timestamp:

 o.prototype.toNumber = function(e) {
    if (!e && this.hi >>> 31) {
        var t = 1 + ~this.lo >>> 0,
            n = ~this.hi >>> 0;
        return t || (n = n + 1 >>> 0), -(t + 4294967296 * n)
    }
    return this.lo + 4294967296 * this.hi
}
1
  • 1
    I see no way to map that integer to those bytes. It you convert 1632933900000 to bytes using the most common encoding scheme you get [1, 124, 50, 113, 238, 224] in big-endian, [224, 238, 113, 50, 124, 1] in little endian. Commented Sep 29, 2021 at 0:33

2 Answers 2

3

224 221 199 147 195 47 is the decimal representation of E0 DD C7 93 C3 2F ... which is 247243140743983 in decimal. Maybe not the whole dword is the timestamp ...for comparision: 01 7C 32 71 EE E0 or 61 54 98 0C. One can already notice by the first digit, how far off this approach is.


That number in JS might be of type BigInt:

BigInt("0x017C3271EEE0")

But BigInt("0xE0DDC793C32F") still gives 247243140743983.

Sign up to request clarification or add additional context in comments.

4 Comments

Wait... so how did you get this [224, 221, 199, 147, 195, 47] to 017C3271EEE0 ... or that's just example from the result output?
Converting decimal to hexadecimal notation... with the stock Microsoft calculator, when switching to "programmer" mode .
Thank you for your time, it will be something with LongBits, maybe even custom encoded time... I'll figure it out.
Since the value is not being represented in a raw format... the most easy might be to just copy the JS code into a PHP IDE... and replicate all the bit-shifting. It seems to be ZigZag encoding (or similar), which eg. protocol buffers use.
1

Just to complete this answer I used following stuff, but I have absolutely no clue what it does :D

<?php
function int64_helper($obj)
{
    $e = (object) ['lo' => 0, 'hi' => 0];
    
    
    if (!($obj->len - $obj->pos > 4)) {
        for ($i = 0; $i < 3; $i++) {
            if ($obj->pos >= $obj->len) throw new Exception('ERROR RANGE');
            $e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos]) << (7 * $i)), 0);
            if ($obj->buf[$obj->pos++] < 128) return $e;
        }
        $e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos++]) << (7 * $i)), 0);
        return $e;
    }
    
    for ($i = 0; $i < 4; $i++) {
        
        $e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos]) << (7 * $i)), 0);
        
        if ($obj->buf[$obj->pos++] < 128) return $e;
    }
    
    $e->lo = rrr(($e->lo | ((127 & $obj->buf[$obj->pos]) << 28)), 0);
    $e->hi = rrr(($e->hi | rr((127 & $obj->buf[$obj->pos]), 4)), 0);
    if ($obj->buf[$obj->pos++] < 128) {
        return $e;
    }
    
    if ($obj->len - $obj->pos > 4) {
        for ($i = 0; $i < 5; $i++) {
            $e->hi = rrr($e->hi | ((127 & $obj->buf[$obj->pos]) << (7 * $i) + 3), 0);
            
            if ($obj->buf[$obj->pos++] < 128) return $e;
        }
    }
    else {
        for ($i = 0; $i < 5; $i++) {
            if ($obj->pos >= $obj->len) throw new Exception('ERROR RANGE');
            $e->hi = rrr($e->hi | ((127 & $obj->buf[$obj->pos]) << (7 * $i) + 3), 0);
            
            if ($obj->buf[$obj->pos++] < 128) return $e;
        }
    }
    
    throw new Exception("invalid timestamp encoding");
}


/**
* Date time
*/
function int64($obj)
{
    $e = int64_helper($obj);
    
    $mst = $e->lo + 4294967296 * $e->hi;
    
    $t = substr($mst, 0, -3); // poslední 3 nuly dávám pryč
    
    $s = date("Y-m-d H:i:s", $t); // prague timezone
    
    return $s;
}


/**
 * The >>> javascript operator in php x86_64
 * Usage: -1149025787 >>> 0 ---> rrr(-1149025787, 0) === 3145941509
 * @return int
 */
function rrr($v, $n)
{
    return ($v & 0xFFFFFFFF) >> ($n & 0x1F);
}

/**
 * The >> javascript operator in php x86_64
 * @return int
 */
function rr($v, $n)
{
    return ($v & 0x80000000 ? $v | 0xFFFFFFFF00000000 : $v & 0xFFFFFFFF) >> ($n & 0x1F);
}


/**
 * The << javascript operator in php x86_64
 * @return int
 */
function ll($v, $n)
{
    return ($t = ($v & 0xFFFFFFFF) << ($n & 0x1F)) & 0x80000000 ? $t | 0xFFFFFFFF00000000 : $t & 0xFFFFFFFF;
}

1 Comment

This hi/lo (with three hexadecimal digits each) has to do with bit numbering. Different variable names might also make it more readable.... while I still think that a library alike GMP, could do the same, while eventually even speed up low-level operations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.