sfrazor
Members-
Content Count
57 -
Joined
-
Last visited
Everything posted by sfrazor
-
Thanks FPiette. I do use the ICS and Indy components. Ping -t is just a simple example. The end goal would be to kill a stuck process that I started after x seconds/minutes and capture the output until that time. There is a couple of good DOS components that are overkill, but I don't learn that way. 🙂 The WaitForSIngleObject is set for 5 seconds. When it expires it falls through like I would expect and the taskkill, closehandle etc get executed as I would think. But still the ping -t doesn't die. I'm using ping -t as an example but other continuous commands suffer the same. What I don't understand is, even when the taskkill or closehandle get executed the procerss doesn't die. I don't directly have the PID of ping so I'm missign something. From what I can tell, the dwProcessID is the PID of the cmd.exe that is created but when that is killed, the ping keeps going even though the parent is gone. Maybe there is a better way to careate a process, monitor it and kill it after a time, if its still running.
-
I'm wanting to extend a Windows app via plugins. I'm sure this has come up before but I'm not quite sure what to search for. I have a standard windows Form app that has a menu across the top and side. I'd like to add plugins (new menu options) to the menu on the side. I'd like for the plugin to be scripted so any dev can add them. I down want be stuck producing a dll that has to be put in place but prefer a script (not picky about the scripting language) Add the plugin script to a folder and when the app starts/restarts the new menu item shows up and is interactive with the main app. Simplicity is key.... I'm sure I can do it but it sounds more difficult than it probably is. This is something I'm toying with after seeing a python app that allows plugins via very small and simple python scripts and am curious if I can accomplish something similar. Can someone point me to an example perhaps? Or ideas?
-
Thanks Frost, for me, this whole exercise is learning. I've never tried to dynamically extend an app other than dll's. I'd think including a script engine would be a good way to go. What would really be good is to be able to create the plugin from within the app. So a script editor perhaps available in an admin area. Sort of a mini Delphi editor maybe. I've read a bit about some of the scripting tools in Delphi having access to the main app by exposing certain classes/objects. That's also interesting but I'm not confident on how to tie it all together. Sorry if I sounds like I'm rambling. This weekend I'll dive in a bit. My bet is that someone has been down this road already, and solved it. All of this came from a python app I was working on. Its easy to include a plugin because the entire language is scripting and the groundwork for pulling in plugins was already in place. It was prone to lots of debugging, so I was thinking maybe I could do it in Delphi easier once I got it straight.
-
It looks like TNetHTTPClient trusts all CA's by default. Then leaves it up to the developer to verify the public key. But, is there a way to only allow or validate against a specific CA? I've done some searching and reading and Indy comes up with some examples but I don't see anything on TNetHTTPClient and how to accomplish this.
-
Thanks for the response. I really like ICS. Last visit to the site there was some info on the use of YuOpenSSL. I'm going to go search when I'm done here. Specifically is there a how-to to add YuOpenSSL as an alternative? Last look it was a bit cryptic for me to understand.
-
Thanks, and yes. I'm using the callback for validating (cert pinning). So I was confused. The components utilize native cert validation unless the callback is in place. I was confused what the pubkey was and I found out it is the modulus. My lack of understanding of the validating the cert. Or overall lack of understanding. But I'm learning!
-
Right, what I'm saying is our requirements doc produced by our Project Manager dictates what's wanted for a specific dev task. In this case (and not always) he asked for a single dll deliverable. The dll is obviously including https comms. Makes my job interesting to say the least.
-
Hey Frost, Sorry for the late reply. I can make suggestions for projects when things just don't make sense. This forum is good at pointing those things out. Like why no SSL dll's. But the short of it is, the requirement of packaging a single deliverable executable or DLL which the PM describes as no openssl DLL's if at all possible. This leaves me with Indy and ICS for comms components using YuOpenSSL.
-
I've done some searching and see very minimal information about running Delphi in a CI/CD pipeline on gitlab. I wish it was CMAKE driven but MSBUILD is OK I suppose, I have a successful CI/CD pipeline running with MSBuild. Finally. My question is specific to gitlab and what files need to be committed to the repo for proper collaboration. In my environment all changes are peer reviewed and accepted for merge. However, the commit changes are littered with .dproj, .local, .grpproj and cache XML files. Obviously the .cache files can be added to the .gitignore. What exactly is required to commit to gitlab for proper collaboration? The catch is, if I make changes to my local environment, it gets pushed which is not needed If I add a project to the group It gets pushed via the grpproj file, which is needed so the next person checking out the project has the new project in the group, The .grpproj seems to get pushed every time by the fact that its touched. Maybe I'm wrong. All of t his seems very messy. Is there a proper way to accomplish all of this in git that will eliminate all of the change cruft from being pushed?
-
Yes, I saw that ICS also has the ability to build against YUOpenSSL. I may have to hit up Remy for some hand holding if I decide to use Indy and YUOpenSSL. If we work it out, I'll post the details here.
-
I made mods to my .gitignore based on your example. Thanks! I'll see how that does. Also pulled down the projectmagician to give that a try....
-
Thanks Frost. I did end up using the windows API like you mentioned. Not what I would have liked. I would have used Indy if they had a way to eliminate the openssl distribution requirement. On that note, I see there is an option for YUOpenSSL (or whatever its called) that interests me. But no step-by-step for dummies (that I find) on how to implement it. Add the compiler options, add the YUOpenSSL library and install the new alternate Indy in to Delphi. But its promising. Indy has all of the above Cert details surfaced which is what I really need.
-
At the moment I'm playing with TNetHTTPClient.UseDefaultCreedentials:= False to turn off the default credential validation then TNetHTTPClient.CredentialStorage.AddCredentials(MyCreds); Trying to turn off the accept ALL CA's and insert my own. I have no idea if I'm heading in the right direction. I don't see any good examples of how to add my own CA cert and validate a server CA against it.
-
When building a DLL, I have a series of arrays that I want compiled together in the binary. Perhaps like a packed record. I'm not sure I'm asking this question correctly.... For example item1: array [0..64] of ansichar item2: array [0..64] of ansichar item3: array [0..64] of ansichar I want the compiler/linker to keep them together in the binary so I can open the DLL and do a replace on 192 contiguous bytes. The compiler seems to move these around and not contiguous. Is there a way, or a better way to achieve this without using a packed record? I've searched the compiler and linker flags but I don't see anything that looks obvious. The Align flag doesn't seem to be what I'm looking for.
-
Sorry for the late reply. That was a wow moment! I honestly didn't even think of that. That's a MUCH easier refactor than I was getting ready to do. Thanks Remy. I'll give it a try. I'll have to figure out how to add a search marker so I can scan the binary for the beginning of the array.
-
Thank you. I was afraid that was the answer. I have some refactoring to do of some rather ugly code.
-
I have a common.pas file that contains a procedure dbgWriteLn. It would seem I would have to get a valid Handle for the current cmd.exe process and write to that. The procedure looks like this: Atach Console is defined thus: function AttachConsole(dwProdessID: Integer): boolean; stdcall external 'kernel32.dll'; function FreeConsole(): Boolean; stedall; external 'kernel32.dll' procedure DbgWriteLn(const outstr: string); begin {$IFDEF DEBUG} AttachConsole(-1); WriteLn(outstr); FreeConsloe; {$ENDIF} end; Using a simple exe that loads the dll via LoadLIbrary and GetProcAddress, I call the entry point and all is fine. Except I need to have debug output on the cmd.exe console when the loader loads and runs the dll. The loader works fine. There is no output from the dbdWriteLn within the dll. After a bit of searching I don't find anything definitive. I read that WriteLn is not a typical replacement for something like printf. Writeln output is given special handling within the compiler if I understand it properly. The dll gets passed to a tester for review and the release and debug version are included. He needs to see the debug outpout from the dll. In C printf works regardless. I need something similar in delphi. Or is there a better way to achieve the output to the console (stdout) from within a dll that is run via a cmd.exe console?
-
Update: After some reading and trying to understand why WriteLn is not working in the above code, I tried to this with some success: Still not sure if this is the best way to accomplish this. procedure DbgWriteLn(const outstr: string); var WinHandle: THandle; written: cardinal; begin if outstr.length = 0 then Exit; {$IFDEF DEBUG} WinHandle:= GetStdHandle(std_Output_Handle); if (WinHandle <> Invalid_Handle_Value) then begin WriteConsole(WinHandle,Pointer(outstr),outstr.length,written,nil); end; {$ENDIF} end;
-
In the past I've used easy curl/libcurl in C to accomplish some tasks. I am novice when it comes to this so forgive me if I construct my questions incorrectly. I'm trying to understand how to accomplish the following in native Delphi using the TNetHTTPClient/NetHTTPRequest component. Rather than post a bunch of embarrassing code, I'll post some C Code best I can recall that I've worked through in the past and see if I can accomplish it in Delphi. I don't mind reading but I didn't see anything that addressed this on a simple level I can understand. If I'm understanding, there is nothing CURL is doing here that a HTTP Client can't accomplish. In 'C' //first some curl basic setup.... then: curl_mimepart *part; curl_addpart(mime); curl_mime_name(part, "data"); curl_mime_filename(part, "filename"); //there is no filename but curl is odd and needs it to send as if binary data if I remember correctly. curl_mime_data(part, databuf, data_len); curl_mime_type((part, "application/octet-stream"); // NetHTTPClient1.ContentType:= 'application/octet-stream' ?? curl_easy_setopt(curol, CURLOPT_MIMEPOST, mime); // NetHTTPRequest1.MethodString:= 'POST' ?? curl_easy_perform(curl); What am I trying to accomplish? Sending a simple binary data buffer as if it were a file.
-
Remy, Thanks for the details. It helps. This should go a bit further in clarifying my process..... PostData: TMultipartFormData; ms: TMemoryStream; ResultString: TStringStream; URL: string CompressedWithBytes: string;; CompressedLen: Cardinal; //unsigned is required by the server .... URL := 'https://10.1.1.1:8443/' ms := TMemoryStream.create ResultString := TStringStream.create; PostDat := TMultipartFormData.create; CompressedWithBytes := ZipAddJSON(JSONDATA); // Returns string with 4 bytes added to header (27 02 00 00 <GZIP-JSON data>) CompressedLen := Length(CompressedWithBytes); ms.write(CompressedWithBytes, CompressedLen); Postdata.AddStream('data', ms, 'filename', 'application/octet-stream); NetHttpRequest.Post(URL,PostData); Server Side Python3 Receives HTTP(S) POST ... filedata = request.files.get('data'); // verifies data keyword is there prints error if missing // verifies application/octet-stream is there prints error if missing data = file.stream.read() file.close() size = int.from_bytes(data[:4], 'little) <- this should be the 4 byte size of the uncompressed data print(f"First four bytes: {size}") First four bytes: 88434780 <--should be 27020000 which is the first 4 bytes added to the data before sending data = zlib.decompress(data[4:], buffsize=int.from_bytes(data[:4], "little")) <---------- fails excep zlib.error as e: raise HTTPError(400, f"Failed to decompress data: {e}") //Exception Prints: //Error in app: Failed to decompress data: Error -3 while decompressing data: incorrect header check I'll see if I can provide the curl raw data... Its actually production code that send periodic updates to a server. I also don't know how to do that with TNETHTTPCLient or TNETHTTPRequest 😞
-
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.
-
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
-
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.
-
Before you posted this I tried it. I can confirm this is correct... But you already knew that. 🙂
-
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.