Added experimental options to change the Windows agent resource executable information.

Ylian Saint-Hilaire committed Jun 20, 2022 at 12:03 UTC 44994a5a9bc49726076b8ecbcc269d56d25325c1
3 files changed +39 -7
authenticode.js
+1 -4
@@ -1639,7 +1639,6 @@ function createAuthenticodeHandler(path) {
1639
1640 // Re-encode the executable signature block
1641 const p7signature = Buffer.from(forge.asn1.toDer(pkcs7der).data, 'binary');
1642 - console.log('r3');
1642
1643 // Write the file with the signature block
1644 writeExecutableEx(output, p7signature, written, func);
@@ -1830,16 +1829,14 @@ function start() {
1829 if (err == null) { console.log("Done."); } else { console.log(err); }
1830 if (exe != null) { exe.close(); }
1831 });
1833 - return;
1832 } else {
1833 console.log("Changing resources and signing to " + args.out);
1834 exe.writeExecutable(args, cert, function (err) { // Signing with resources decoded and re-encoded.
1835 if (err == null) { console.log("Done."); } else { console.log(err); }
1836 if (exe != null) { exe.close(); }
1837 });
1840 - return;
1838 }
1842 - console.log("Done.");
1839 + return;
1840 }
1841 if (command == 'unsign') { // Unsign an executable
1842 if (typeof args.exe != 'string') { console.log("Missing --exe [filename]"); return; }
meshcentral.js
+28 -3
@@ -2886,6 +2886,21 @@ function CreateMeshCentralServer(config, args) {
2886 if (args.agenttimestampserver === false) { timeStampUrl = null; }
2887 else if (typeof args.agenttimestampserver == 'string') { timeStampUrl = args.agenttimestampserver; }
2888
2889 + // Setup agent signing arguments
2890 + const signingArguments = { desc: signDesc, url: signUrl, time: timeStampUrl };
2891 +
2892 + // See if we have any resources we need to change in the agent
2893 + var resChanges = false;
2894 + if ((domain.agentfileinfo != null) && (typeof domain.agentfileinfo == 'object')) {
2895 + if (typeof domain.agentfileinfo.filedescription == 'string') { signingArguments.FileDescription = domain.agentfileinfo.filedescription; resChanges = true; }
2896 + if (typeof domain.agentfileinfo.fileversion == 'string') { signingArguments.FileVersion = domain.agentfileinfo.fileversion; resChanges = true; }
2897 + if (typeof domain.agentfileinfo.internalname == 'string') { signingArguments.InternalName = domain.agentfileinfo.internalname; resChanges = true; }
2898 + if (typeof domain.agentfileinfo.legalcopyright == 'string') { signingArguments.LegalCopyright = domain.agentfileinfo.legalcopyright; resChanges = true; }
2899 + if (typeof domain.agentfileinfo.originalfilename == 'string') { signingArguments.OriginalFilename = domain.agentfileinfo.originalfilename; resChanges = true; }
2900 + if (typeof domain.agentfileinfo.productname == 'string') { signingArguments.ProductName = domain.agentfileinfo.productname; resChanges = true; }
2901 + if (typeof domain.agentfileinfo.productversion == 'string') { signingArguments.ProductVersion = domain.agentfileinfo.productversion; resChanges = true; }
2902 + }
2903 +
2904 // Setup the pending operations counter
2905 var pendingOperations = 1;
2906
@@ -2905,7 +2920,7 @@ function CreateMeshCentralServer(config, args) {
2920 }
2921
2922 // Open the original agent with authenticode
2908 - var signeedagentpath = obj.path.join(serverSignedAgentsPath, obj.meshAgentsArchitectureNumbers[archid].localname);
2923 + const signeedagentpath = obj.path.join(serverSignedAgentsPath, obj.meshAgentsArchitectureNumbers[archid].localname);
2924 const originalAgent = require('./authenticode.js').createAuthenticodeHandler(agentpath);
2925 if (originalAgent != null) {
2926 // Check if the agent is already signed correctly
@@ -2937,8 +2952,18 @@ function CreateMeshCentralServer(config, args) {
2952 xagentSignedFunc.objx = objx;
2953 xagentSignedFunc.archid = archid;
2954 xagentSignedFunc.signeedagentpath = signeedagentpath;
2940 - obj.debug('main', "Code signing agent with arguments: " + JSON.stringify({ out: signeedagentpath, desc: signDesc, url: signUrl, time: timeStampUrl }));
2941 - originalAgent.sign(agentSignCertInfo, { out: signeedagentpath, desc: signDesc, url: signUrl, time: timeStampUrl }, xagentSignedFunc);
2955 + const xsigningArguments = Object.assign({}, signingArguments); // Shallow clone
2956 + xsigningArguments.out = signeedagentpath;
2957 +
2958 + obj.debug('main', "Code signing agent with arguments: " + JSON.stringify(signingArguments));
2959 + if (resChanges == false) {
2960 + // Sign the agent the simple way, without changing any resources.
2961 + originalAgent.sign(agentSignCertInfo, xsigningArguments, xagentSignedFunc);
2962 + } else {
2963 + // Change the agent resources and sign the agent, this is a much more involved process.
2964 + // NOTE: This is experimental and could corupt the agent.
2965 + originalAgent.writeExecutable(xsigningArguments, agentSignCertInfo, xagentSignedFunc);
2966 + }
2967 } else {
2968 // Signed agent is already ok, use it.
2969 originalAgent.close();
sample-config-advanced.json
+10
@@ -286,6 +286,16 @@
286 "image": "agent-logo.png",
287 "fileName": "compagnyagent"
288 },
289 + "_agentFileInfo": {
290 + "__COMMENT__": "This section is experimental",
291 + "_filedescription": "sample_filedescription",
292 + "_fileversion": "0.1.2.3",
293 + "_internalname": "sample_internalname",
294 + "_legalcopyright": "sample_legalcopyright",
295 + "_originalfilename": "sample_originalfilename",
296 + "_productname": "sample_productname",
297 + "_productversion": "0.1.2.3"
298 + },
299 "_assistantCustomization": {
300 "title": "Company® Product™",
301 "image": "assistant-logo.png",