Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERR_BUFFER_OUT_OF_BOUNDS exception on ref.reinterpret call #42

Open
Qaho opened this issue Aug 21, 2020 · 11 comments
Open

ERR_BUFFER_OUT_OF_BOUNDS exception on ref.reinterpret call #42

Qaho opened this issue Aug 21, 2020 · 11 comments

Comments

@Qaho
Copy link

Qaho commented Aug 21, 2020

Hi,

I'm trying to get some data from a protected file using native Crypt32.dll.

I'm getting an ERR_BUFFER_OUT_OF_BOUNDS exception on ref.reinterpret call with this piece of code:

const fs = require("fs");
const ref = require("ref-napi");
const ffi = require("ffi-napi");
const struct = require("ref-struct-napi");

const DATA_BLOB = struct({
    cbData: ref.types.uint32,
    pbData: ref.refType(ref.types.byte)
});
const PDATA_BLOB = new ref.refType(DATA_BLOB);
const Crypto = new ffi.Library('Crypt32', {
    "CryptUnprotectData": ['bool', [PDATA_BLOB, 'string', 'string', 'void *', 'string', 'int', PDATA_BLOB]],
    "CryptProtectData": ['bool', [PDATA_BLOB, 'string', 'string', 'void *', 'string', 'int', PDATA_BLOB]]
});

export class Protect {

    private path: string
    private entropy: Buffer
    private dataBlobEntropy: any
    private dataFile: any
    private rawData: any

    constructor(path: string) {
        this.path = path
        this.entropy = Buffer.from([0x1, 0x2, 0x3, 0x4]);

        this.dataBlobEntropy = new DATA_BLOB()
        this.dataBlobEntropy.pbData = this.entropy
        this.dataBlobEntropy.cbData = this.entropy.length
    }

    public getUnprotected(): any {
        
        if (this.readProtectedFile()) {
            this.rawData = this.decryptProtectedFile()
        }
        else {
            throw "Unable to read protected file " + this.path
        }

        return this.rawData
    }

    private readProtectedFile(): Boolean {
        console.log('readProtectedFile')
        let success: Boolean = false

        try {
            console.log('Reading protected file ' + this.path)
            let data = fs.readFileSync(this.path)
            //console.log(data) 
            this.dataFile = data;
            console.log('Read protected file OK (Size: ' + this.dataFile.length + ')')
            success = true;
        } catch (err) {
            console.error(err)
        }

        return success;
    }

    private decryptProtectedFile(): any {
        console.log('decryptProtectedFile')
        let buf = Buffer.from(this.dataFile);
        let dataBlobInput = new DATA_BLOB();
        dataBlobInput.pbData = buf;
        dataBlobInput.cbData = buf.length;

        let dataBlobOutput = ref.alloc(DATA_BLOB);
        let result = Crypto.CryptUnprotectData(dataBlobInput.ref(), null, this.dataBlobEntropy.ref(), null, null, 0x4, dataBlobOutput);

        if (!result) {
            console.error('Decrypt failed')
            return;
        }

        console.log('Decrypt SUCCESS')
        let outputDeref = dataBlobOutput.deref();
        console.log('Decrypt deref OK')
        console.log('Decrypt cbData: ' + outputDeref.cbData)
        let outputBytes = ref.reinterpret(outputDeref.pbData, outputDeref.cbData, 0);
        console.log('Decrypt reinterpret OK')
        return outputBytes;
    }
}

Exception stacktrace:

RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: "length" is outside of buffer bounds
    at fromArrayBuffer (buffer.js:463:15)
    at from (buffer.js:288:14)
    at Object.reinterpret (c:\projects\unprotect\node_modules\ref-napi\lib\ref.js:776:23)
    at Protect.decryptProtectedFile (c:\projects\unprotect\dist\protect.js:65:31)
    at Protect.getUnprotected (c:\projects\unprotect\dist\protect.js:26:33)
    [...]
  code: 'ERR_BUFFER_OUT_OF_BOUNDS'
}
Process exited with code 1

The thing is that it's working perfectly when using the ref (from github:lxe/ref#node-12), ref-struct (from github:lxe/node-ref-struct#node-12) and ffi (from github:lxe/node-ffi#node-12) libs (instead of ref-napi, ref-struct-napi and ffi-napi), but I need the napi libs for compatibility issue with electron and last node versions.

Node: v12.14.1
Npm: 6.13.4

Could you have a look on this please?
Let me know if you need more information.
Thanks a lot in advance.

@addaleax
Copy link
Contributor

Can you share the output of the console.log statements you’re providing, and maybe the value of outputDeref.pbData.buffer.length?

@Qaho
Copy link
Author

Qaho commented Aug 21, 2020

Sure:

readProtectedFile
Reading protected file src\__test__\test-cases\file1
Read protected file OK (Size: 774650)
decryptProtectedFile
Decrypt SUCCESS
Decrypt deref OK
Decrypt cbData: 774506
Decrypt outputDeref.pbData.buffer.length: undefined
Decrypt outputDeref.pbData.length: 1
Waiting for the debugger to disconnect...
c:\projects\unprotect\node_modules\ref-napi\lib\ref.js:776
  const rtn = exports._reinterpret(buffer, size, offset || 0);
                      ^

RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: "length" is outside of buffer bounds
    at fromArrayBuffer (buffer.js:463:15)
    at from (buffer.js:288:14)
    at Object.reinterpret (c:\projects\unprotect\node_modules\ref-napi\lib\ref.js:776:23)
    at Protect.decryptProtectedFile (c:\projects\unprotect\dist\protect.js:65:31)
    at Protect.getUnprotected (c:\projects\unprotect\dist\protect.js:26:33)
    [...]
  code: 'ERR_BUFFER_OUT_OF_BOUNDS'
}

FYI, outputDeref.pbData.length is always set to 1 weither the exception is thrown or not.

@Qaho
Copy link
Author

Qaho commented Aug 24, 2020

I have enabled debug logs:
ERR_BUFFER_OUT_OF_BOUNDS-debugLogs.txt

Hope this helps!

@lucasfelipecdm
Copy link

Hi, I have the same problem, when I'm using ref-napi 1.5.2 its work fine, but I need the napi libs for compatibility issue with electron and last node versions too, and change to 3.0.1 then I got this error when use reinterpret inside a ffi.Callback function.

captureCallback = ffi.Callback('void', ['pointer', 'uint', 'uint', 'pointer'], (ctx: any, rsv: number, dtSize: number, dt: Buffer) => { const dtReinterpreted = new dpfpdd_capture_callback_data_0(ref.reinterpret(dt, dtSize)); ..... ..... });

I hope it is useful.

@avivsalman
Copy link

Hi, same error for me, does anyone can help us?

Thanks 👍

@avivsalman
Copy link

Anyone? it's very urgent :)

@sangshuduo
Copy link

commented on another issue too. #50 (comment) . wondering if any progress.

@Yongle-Fu
Copy link

Hi, same error for me, does anyone can help us?

Thanks 👍

@liujun-dlink
Copy link

liujun-dlink commented Jun 25, 2021

I think the useage of "reinterpret" needs to be changed.
image

@mrboots123
Copy link

I was having a similar issue, turns out ref-struct-napi was incompatible with ref-napi. The issue was resolved when switching to ref-struct-di as mentioned in the docs.

@doggkruse
Copy link

It's possible that my fix for #72 will address this. In some cases the underlying array buffer was not created large enough if a previous array buffer at the same address existed (and was smaller)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants