Fake C++ Compiler with Node.js - Part 1
Tags: cpp, node, javascript, programming
Published: 2023-03-25 06:37:38

## Why fake? 

Let's use the system [Embedding Files in an Executable](https://dev.to/gurigraphics/embedding-files-in-an-executable-linuxwsl2-35b1) to turn Node.js into a **Fake C++ Compiler**.

Fake because it will change the content of resources directly from binary or hexadecimal.

## What's the use of that?

For a server to compile a C++ program we need to install several gigabytes of libraries, a dedicated Linux or Windows server, a reasonable amount of RAM and CPU to do the processing.

To just modify an executable we will only need a **server node.js**. 
We can even do this with javascript on the client-side frontend.

## Part 1 - C++


### 1.1) Create main.cpp

```cpp
#include <iostream>
#include "resources.h"

int main() {
    std::cout << GetResource() << std::endl;
    return 0;
}

```

### 1.2) Create resources.h

```cpp
#include <windows.h>

#define IDI_MYICON  101
#define TEXTFILE   256
#define IDR_DATA1  255

void LoadFileInResource(int name, int type, DWORD& size, const wchar_t*& data){
    HMODULE handle = ::GetModuleHandleW(NULL);
    HRSRC rc = ::FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(type));
    HGLOBAL rcData = ::LoadResource(handle, rc);
    size = ::SizeofResource(handle, rc);
    data = static_cast<const wchar_t*>(::LockResource(rcData));
}

std::string GetResource(){
    DWORD size = 0;
    const char* data = NULL;
    LoadFileInResource(IDR_DATA1, TEXTFILE, size, reinterpret_cast<const wchar_t*&>(data));  
    std::string content(data, size);
    return content;
}

```

### 1.3) Create resources.rc

```
#include <windows.h>
#include "resources.h"

IDI_MYICON ICON "favicon.ico"
IDR_DATA1 TEXTFILE "data.txt"

VS_VERSION_INFO     VERSIONINFO
FILEVERSION       1,0,0,1
PRODUCTVERSION    1,0,0,1
FILEFLAGSMASK 0x3fL

#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x2L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "CompanyName", "CompanyName"
            VALUE "LegalCopyright", "(c) CompanyName. All Rights reserved."
            VALUE "ProductName", "ProductName"
            VALUE "ProductVersion", "1,0,0,1"
            VALUE "FileDescription", "ProductName"
            VALUE "InternalName", "ProductName"
            VALUE "OriginalFilename", "main.exe"
            VALUE "ShellIntegrationVersion", "2"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0416, 1200
    END
END
```

### 1.4) Download 1 favicon.ico

https://favicon.io/emoji-favicons/


### 1.5) Create data.txt

```
<a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5>
```

### 1.6) Generate resources.res

```
windres.exe -i "resources.rc" --input-format=rc -o "resources.res" -O coff
```


### 1.7) Compile

```
g++ main.cpp -o main.exe -I./ -static-libgcc -static-libstdc++ resources.res 
```

### 1.8) Test

```
main
```

Console Output
```
<a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5>
```


### 1.9) Search hex

Open **main.exe** in an editor hexadecimal or run

```
certutil -encodehex main.exe hex.txt
```

### 1.10) Get address

Search by 
```
<a1
```
The position of "<" I found in the column 9 of line 000a8db0
This is the beginning of the resources region
```
0xa8db8
```

![Bytes positions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5y1usekw2cz9l922o2o.png)


Search by 
```
5>
```

The position of ">" I found in the column 16 of line 000a8dc8
This is the end of the resources region
```
0xa8dd7
```

For now just save these addresses




## Part 2 - Node.js

### 1. Node start

```
mkdir node_cpp
cd node_cpp
mkdir uploads
npm init -y
```


### 2. Copy "main.exe" to folder "node_cpp\uploads"

```
copy ..\main.exe .\uploads
```

### 3. Install

```
npm i fs
npm i path
```

### 3. Create path_join.js

This file will be used to resolve the directories path 

```js
const path = require('path')

const path_join = function( file, folder ){
  if( folder ) return path.join(__dirname, `/${folder}/${ file }`)
  return path.join(__dirname, `/${ file }`)
}

module.exports = path_join; 
```

### 4. Create slicer.js

This file will be used to cut the executable into 3 parts: **header**, **middle**, **footer**

Middle is the part that we want to modify and update using just node.js.

```js
const fs = require('fs')

const slicer = function( exe_path, result_path, entry_start, entry_end ){

  var file_data;

  // Set positions
  const file_start = parseInt( entry_start, 16 );
  const file_end = parseInt( entry_end, 16 );

  // Get exe
  const input_data = fs.readFileSync( exe_path );

  // Slice
  if( entry_end == "end" ){
    file_data = input_data.slice( file_start )
  }else{
    file_data = input_data.slice( file_start, file_end )
  }  

  // Write
  fs.writeFileSync( result_path, file_data );

  console.log('Binary file sucessfull created!');
} 

module.exports = slicer; 
```

### 5. Create data.txt in "node_cpp/uploads"

This will be the content we will replace
Attention: this content cannot be greater than the previous content

```
1234567890
```


### 6. Create replaceBinaryText.js

This file will be used to take the contents of **middle.exe** and generate a **new_middle.exe** with the new contents. If the new content is smaller, it will fill with **0x0000** until it reaches the original size.
 

```js
const fs = require('fs')

const replaceBinaryText = function( data_path, input_path, output_path ){

  // Get bin
  const exe = fs.readFileSync( input_path );
  const min_size = exe.length;

  // Get text
  const input_data = fs.readFileSync( data_path );
  const data_size = input_data.length;

  if( data_size > min_size ){

    console.log(`File Error. Maximum size is ${min_size}`);

  }else{

    // Fill
    const padding_buffer = Buffer.alloc(min_size - data_size, 0x00);

    // Concat
    const output_buffer = Buffer.concat([input_data, padding_buffer]);

    // Write
    fs.writeFileSync(output_path, output_buffer, 'binary');

    console.log('Binary file sucessfull created!');
  }
}

module.exports = replaceBinaryText; 
```



### 7. Create merge3binary.js

This file will be used to join the 3 binaries: **header.exe**, **middle.exe** and **footer.exe** to create the **final.exe**.

```js
const fs = require('fs')

const merge3binary = function( header, middle, footer, output_path ){

  const header_data = fs.readFileSync( header );
  const middle_data = fs.readFileSync( middle );
  const footer_data = fs.readFileSync( footer );

  const merged_buffer = Buffer.concat([header_data, middle_data, footer_data]);

  fs.writeFileSync(output_path, merged_buffer, 'binary');

  console.log('Binary file sucessfull created!');
}

module.exports = merge3binary; 
```


### 8. Create main.js

Finally let's put it all together. Now let's use those addresses **0xa8db8** and **0xa8dd7** + 1

```js
var slicer = require('./slicer')
var path_join = require('./path_join')
var merge3binary = require('./merge3binary')
var replaceBinaryText = require('./replaceBinaryText')

const main = function(){

  var folder = "uploads"

  var input_path = path_join( "main.exe", folder )
  var output_path = path_join( "final.exe", folder )

  var header_path = path_join( "main_header.exe", folder )
  var middle_path = path_join( "main_middle.exe", folder )  
  var footer_path = path_join( "main_footer.exe", folder )

  var data_path = path_join( "data.txt", folder )
  var new_path = path_join( "main_middle_updated.exe", folder )
  
  var adress_start = "0xa8db8"
  var adress_end = "0xa8dd8" // 0xa8dd7 + 1

  // -------- Generate 3 slices
  slicer( input_path, header_path, "0x00000", adress_start)
  slicer( input_path, middle_path, adress_start, adress_end)
  slicer( input_path, footer_path, adress_end, "end")


  // -------- Update resources region
  replaceBinaryText( data_path, middle_path, new_path )


  // Merge 3 binary
  merge3binary(header_path, new_path, footer_path, output_path)
}

main()
```


### 9. Compile

```
node main.js
```


### 10. Run

```
final
```

Console Output
```
1234567890
```

Now whenever you want to modify it, you just need to modify the content of **data.txt**, and run **node main.js** and finish.


### Fake C++ Compiler with Node.js - Part 2
https://dev.to/gurigraphics/fake-c-compiler-with-nodejs-server-part-2-eag