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",