Jump to content

sfrazor

Members
  • Content Count

    62
  • Joined

  • Last visited

Everything posted by sfrazor

  1. Sorry I started this and abandoned it. This is a learning exercise for me and my employer made me do real work 🙂 So a couple of things. zed: I downloaded the mormot2 and am going to take it for a test drive. We'll see what happens there. Dmitry: I haven't looked at System.Net.HttpClient.Linux.pas yet but I will. Remy: I gave your example code a try. My test server doesn't like the Postdata I'm sending. I didn't realize how little I know about this until now. The server expects <4 byte len><GZIP binary data> like this: https://10.1.1.1:8443/<4 byte len><GZIP binary data> as a POST. At the moment I'd settle for the successful unzip of Postdata so I can see if I munged it some how. But its not getting that far. The 4 bytes get mangled. It is supposed to be byte count of the unzipped data size for a validation check. The GZIP is a mime context with JSON etc within it. I look at the buffer in debug before the Post. It looks good there. It all works as intended with curl ez. When I build the DATA with Delphi I stuff the 4 byte uint value at the head of the data which is a delphi Datastream. Verify its correct. Then append the binary zipped data (mime) to that Datastream and send it. The server spits out some odd value for the first 4 bytes so the GUNZIP fails the byte check. Is the entire content of the NetHTTPRequest1.Post(url, PostData) getting endcoded? I don't want that. So that's what I'm investigating now. I'll throw together some sample code next. It'll be easier to see what I'm doing wrong.
  2. I've read quite a bit and I can usually either be creative enough to come up with a solution or find a solution on the internet. In this case I'm not sure I'm even asking the right question so I'm coming up empty. Hopefully the pro's here can help. My employer says obfuscate. period. To make matters worse, they are not interested in purchasing some obfuscation tool. So, I have to start off by eliminating obvious names within classes that are subsequently transformed in to JSON. Then move on to strings etc... When I ask the question in public I get lectures on Why? What are you trying to hide? Please, I understand but its not an option for me. The string obfuscation I can handle fine. But the class members are a bit more challenging and I'm finding that it can't be done because it requires a pre-process pass in compiling that Delphi doesn't have. I get it, Delphi is strongly typed and variable name substitution is not the best answer. So, I need to find a work-around. Here is the challenge for me: const FNAME = 'abcd' FADDRESS = 'efgh' FCITY = 'ijkl' type TPPI = classs public FNAME: string; FADDRESS: string; FCITY: string; end; I utilize the TJSON.ObjectToJasonString() to flip it to JSON. Work great! The problem is the JSON class names (FNAME, FADDRSS FCITY and more PI) are easily identifiable in the resulting DLL and EXE's and are easily identifiable in the transmitted JSON (yes I can encrypt the JSON string being sent) but that still leaves the DLL/EXE. Instead, I need the substituted abcd, efgh and ijkl to be both in the binary and in the JSON object. I was hoping that eliminating the fields via compiler directive {RTTI EXPLICIT METHODS([]) PROPERTIES ([]) FIELDS([])} would work. However FIELDS([]) eliminates ObjectToJasonString from picking up the fields to build the JSON objects. So eliminating then in the build doesn't seem to be an answer either. I'm pretty sure the obfuscation questions have been asked so pointing me to a topic with some answers is fine. Or, some creative work-arounds would be really appreciated Edit: Using RAD Studio 11 Scott
  3. sfrazor

    Dynamic class member names

    This works fantastic! I couldn't leave my previous solution for the next programmer to untangle so I reverted in the repo and here is what I ended up with. Again constant strings are handled via a simple en/decode function (while I'm wishing can I wish for macro support?). The last of my "mandates" was obfuscate the class field names since they were the most revealing. But as a bonus This solution also takes care of sensitive procedure names. Unit tests still run! So it seems I didn't break anything at a glance. unit Unit4; {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) Fields([vcPublic])} interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, REST.Json, REST.Json.Types; type TPII = class public //Obfuscated Faaaa: string; Fbbbb: string; Fcccc: string; public //Human readable property FNAME: string read Faaaa write Faaaa; property FAddress: string read Fbbbb write Fbbbb; property FCity: string read Fcccc write Fcccc; end; type TForm4 = class(TForm) Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } procedure MyPIIProcedure; //Could be sensative. Needs to be hidden as well... end; var Form4: TForm4; implementation {$R *.dfm} procedure TForm4.Button1Click(Sender: TObject); begin MyPIIProcedure; end; procedure TForm4.MyPIIProcedure; var MyPII: TPII; PIIJSON: string; begin MyPII:= TPII.Create; MyPII.FName:= 'John'; MyPII.FAddress:= 'Main Street'; MyPII.FCity:= 'New York'; PIIJSON := TJSON.ObjectToJsonString(MyPII, [joIndentCaseCamel]); Memo1.Lines.Add('////////////// JSON DATA //////////////'); Memo1.Lines.Add(PIIJSON); MyPII.Free; end; end. To top it off I wrote a small "scrubber" that does the search and replace as mentioned above in the .pas but did it like this: Used this to take care of the actual class names... created an include file with the known-name and an obfuscated equivalent. Wrote a small Delphi console app to do this. Works great in the CI/CD pipeline build. This took care of the remaining 60 or so edge cases hidden in the code. Added the scrubber to the pre-build command to parse out the .pas files needed. Before compile. The resulting binaries are petty darn clean! So thanks again to everyone that chimed in! All great ideas and led to the working solution. No more "plain text" identifiers.
  4. sfrazor

    Dynamic class member names

    Before you posted this I tried it. I can confirm this is correct... But you already knew that. 🙂
  5. sfrazor

    Dynamic class member names

    I appreciate the feedback. The automatic serialization/deserialization is what was there. Based on the git history the code was refactored away from coded JSON objects in favor of taking advantage of newer Delphi JSON automation. And then comes this requirement for "Basic code obfuscation" that is checked pre-release. I considered doing a pre process regex via python in the CI/CD pipeline using markers like you suggested above. I shouldn't have to go through those extremes for any language. I'm really not happy with the way I worked the solution. The code is ugly and difficult to read. I have to reference KEY to work with variables. The classes look like jibberish. Very embarrassing. If there was a 3rd party preprocessor I'd consider that.
  6. sfrazor

    Dynamic class member names

    Thank you everyone for taking the time to work through this with me. I read here often but haven't been in a position to ask for help until this stumped me. Until some pre-process or pre-pass substitution is supported by Delphi the answer was to take the the long names and replace them with coded alternatives and comment the heck out of the code for future developers to follow. Hand-jamming that was a chore even with the help of refactoring. Not very "Delphi" ie pretty, but it works and provides the obfuscation I needed for this mandate. I picked up some other tidbits here as well. If, for example if the decoupling would omit the long names and only embed the alternate names in the RTTI that would have been a perfect solution. Cheers!
  7. sfrazor

    Dynamic class member names

    This is the path I'm headed down. Its a tremendous amount of code, but hey, job security. I thought before I took on that task I'd ask here. I saw where Jedi has a pre-parser but its a bit vague on how to use it and it doesn't seem to exactly fit what I'm wanting to do. Uwe, I've looked at UPX. I don't see where it will handle DLL's unless I missed something. I konw Delphi doesn't NEED a pre parser but man it sure would be nice.
  8. sfrazor

    Dynamic class member names

    I know... I have asked this question almost exactly. Obviously I'm using simple field names that have no value. But in some of the code (In some of the DLL's) there are class names and members that identify proprietary information and they would prefer it to not be there as it paints a target on that binary to be investigated. Yes the information is sensitive which has created a push for obfuscation. Unfortunately I don't get a choice. Obfuscation is something they have adopted and I have to try and figure out. Like I said, strings and data are easy but if a specific name paints a target on one of the DLL's to be investigated it makes it that much quicker for someone to target. I know you've seen these question before but if a person snooping around sees 'kowsscud' instead of 'FPriorityAlgorythm' it makes it less obvious to 'start here' and not just handing it to some malicious person without trying. That seems to be all they want. In the past I've written python scripts that have a blacklist of strings it will search/replace in the CI/CD pipeline. Before I go down that road, I want to make sure I can't handle via native coding. Like I said, I've gotten the same response asking my peers. They respond with Why? What are they thinking, makes no sense, waste of time etc..... The answer may be that Delphi simply can't do it.
  9. sfrazor

    Dynamic class member names

    OK I threw together this example. The attributes decoupling mentioned above works fine for the production of the JSON. However the Fieldnames in the binaries is present. unit Unit4; //{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, REST.Json, REST.Json.Types; type TPPI = class public [JSONName('abcd')] FName: string; //client name [JSONName('efgh')] FAddress: string; //client address [JSONName('ijkl')] FCity: string; //client city end; type TForm4 = class(TForm) Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form4: TForm4; implementation {$R *.dfm} procedure TForm4.Button1Click(Sender: TObject); var MyPPI: TPPI; PPIJSON: string; begin MyPPI:= TPPI.Create; MyPPI.FName:= 'First Name'; MyPPI.FAddress:= 'Main Street'; MyPPI.FCity:= 'New York'; PPIJSON := TJSON.ObjectToJsonString(MyPPI, [joIndentCaseCamel]); // now that we have our JSON lets make if pretty //PrettyJson := TJsonObject.ParseJSONValue(TMJSON); //TMJSON := TJSON.Format(PrettyJson); Memo1.Lines.Add('////////////// JSON DATA //////////////'); Memo1.Lines.Add(PPIJSON); MyPPI.Free; end; That gets my JSON looking like this: ////////////// JSON DATA ////////////// {"abcd":"First Name","efgh":"Main Street","ijkl":"New York"} However these are still in the binary when I do a strings. Which is what started all of this when the binaries were reviewed. ... FName abcd FAddress efgh FCity ijkl TPPI, TPPI ... Scott
  10. sfrazor

    Dynamic class member names

    No, no debug. The Identifiers are all there in Release. Gonna throw together a very small sample. I'll add the decoupling example Uwe mentioned as well.
  11. sfrazor

    Dynamic class member names

    Custom attributes is a good read. It solves another request they made. Thanks! To answer your question, ultimately both would be best. Class and member names within the compiled binary are what caught my employers eye when reviewing the compiled binaries. I feel like if I obfuscate the class field names (not their values as I can post process and obfuscate those) , by default the associated JSON names will be obfuscated when they are processed to JSON which I'd then encrypt the JSON string as a whole. and decrypt it on the receiving end when its consumed. So in the above example I don't want FNAME showing in the binary when I run a simple 'strings' on it, I want 'abcd' to show and not 'FNAME'. When looking at the source, I want the programmer friendly FNAME to be in the source. Not real code here but it would be something like this: cons FNAME = 'abcd' type TPPI = classs public <$FNAME>: string; .... end; at compile time <$FNAME> converts to 'abcd' and when a strings is run on the binary, you only see 'abcd'. Of coarse in Delphi this could create all sorts of problems when referencing that class member later on. Does this help?
  12. sfrazor

    Dynamic class member names

    Thanks François , Yes I can pre/post process the JSON text itself, but the class member names still exist in the binary in their original form. ie 'FNAME' instead of 'abcd'. That's where I'm having difficulty. In 'C' this is easy but in Delphi I can't think of a way to ach ive that level of substitution.
×