Decompiling Delphi Programs [duplicate] - delphi

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Why decompiling a delphi exe, is so easy, compared to others executables built with other programming languages/compilers?

There are a few things that help with reversing delphi programs:
You get the full form data including the name of event handler methods
All members with published visibility have metadata used with RTTI
The compiler is pretty bad at optimizing. It does no whole program optimization and the assembly is usually a straight forward translation of the original source with only minor optimizations. (At least it was in the versions I used, might have improved since then)
All classes, even those compiled with RTTI off have some level of metadata available. In particular it's possible to get the name and inheritance structure of classes. And for any instance of a class you happen to see in the debugger you can get its VMT and thus its class name.
Delphi uses textfiles describing the content of your form and hooks up event handlers by name. This approach obviously needs enough metadata to deserialize that textual representation of a from and hook up the eventhandlers by name.
An alternative some other GUI toolkits use is auto-generating code that initializes the form and hooks up the event handler with code. Since this code directly uses pointers to the eventhandlers and directly assigns to properties/calls setters it doesn't need any metadata. Which has the side-effect that reversing becomes a bit harder.
It shouldn't be too hard to create a program that transforms a dfm file into a series of hardcoded instructions that creates the form instead. So a tool like DeDe won't work that well anymore. But that doesn't gain you much in practice.
But figuring out which evenhandler corresponds to which control/event is still rather easy. Especially since stuff like FLIRT identifies most library functions. So you just need to breakpoint the one you're interested in and then step into the user code.

The statement you make is false. Delphi is not particularly more easy to decompile than code produced by other mainstream compilers.
For .net languages there is Reflector.
C++ is covered in this Stack Overflow question.
Python/Perl/Ruby etc. are interpreted.
If you were able to prove that the results of decompiling a Delphi executable were of significantly higher quality than in other widely used languages then your question would carry more weight.

Story from the trenches: Decompiling a tiny Delphi DLL
I've been through a Delphi decompiling session myself. It was one of those fake-sounding "I lost my sources" thing, I really did lose the sources for a tiny Firebird UDF library. Now I do no better, I didn't jump right into decompiling because the library was so small and I knew a rewrite would be much faster.
This DLL exports a function that looks like this:
function udf_do_some_math(Number1, Number2:Currency): Currency;
After doing the sane thing and rewriting the function and doing some regression tests I discovered some obscure corner-cases where the new function's result wasn't the same as the old function's result! The trouble was, the new function's result was the correct result, the old DLL contained a BUG and I had to reproduce the BUG - with this function consistency is more important then accuracy.
Again, did the sane thing and tried to "guess" at the BUG. I knew it was a rounding issue but simply couldn't figure out what it was. Finally I decided to give decompilers I try. After all this was a small library, the entry-point was straight-forward and I didn't really need re-compilable code, nor 100% decompilation: I only needed enough to figure out the old BUG so I can reproduce it!
Decompiling failed! I tried lots of different decompilers, including a couple of "commercial" ones. Most produced what on the surface looked like good data, but not enough to figure out the old bug. The most promising one, the one with version specific knowledge of the VCL and RTL gave the worst failure: sure, it figured out the RTL calls, gave them names, but failed to locate the exported function! The one function I was interested in wasn't shown int the list of entry points, and it should have been straight forward since it's an exported function.
This decompiling attempt should have been easy because:
The code was fairly simple and not a lot of it.
It was a DLL with an exported function, none of the complexity you'd expect from an event-driven exe.
I wasn't interested in re-compilable code, I simply wanted to find an old bug so I can reproduce it.
I didn't ask for Pascal code, assembler would've been good enough.
I knew precisely what the code was doing and how it was doing it. It wasn't cryptic 3rd party code.
My solution
After decompilers failed me I turned to my own trusty Delphi IDE for debugging. I wrote a small Delphi program that directly imports the function from the DLL, created a fake Firbird memory manager DLL so my DLL can load, called my old function with the parameters I knew would give bad results, steped into the code using the debugger and closely watched the FPU registers. After a few failed attempts I finally noticed a value was popped from the FPU stack as integer where it shouldn't have been Integer so I had my BUG: I mistakenly defined an Integer local variable where I should have used Currency. Armed with that knowledge I was able to reproduce the bug.

Only thing that is easier in Delphi is retrieving VCLs.
After using decompilers like DeDe you will get application user interface but without any logic.
So if you want to retrieve only forms and buttons - Delphi is easier than other compilers, but if you want to know what is going on after clicking on the button you'll need to use ollydbg or other (debugger/disassembler) as for other languages that creates executables.

There are pros and cons. I am not sure what angle your referring to as being easier. There is also a huge difference in a 1 form simple application, versus a very in-depth application that has many forms and tons of classes and functions. It's like Notepad versus Office 2013 (given they were coded in delphi, just an example comparing complexity not language).
In a small app, having the extra information that Delphi apps "usually" contain can make it a breeze. However, in a large application it may "help", but you have a million calls to dig through. They may help you get in the near vicinity, but calls inside of calls inside of calls, then multiple returns used as jumps... makes you dizzy. Then if the app "was" packed or protected, some things can still be a garbled mess. While it may work programming wise, reading it can be a lot harder. I was in one the other day, where all of the strings were encrypted, so "referenced text strings" were no help, and the encryption was not a simple md5 or base64, it was some custom algorithm. Maybe an MD5 with a salt, then base64 encoded? I never could get to the exact method on the strings. I knew what some of them were supposed to be, but couldn't reproduce the method, even though it looked like it was base64, it was the base64 of the string already encrypted some how... I dont rely on text strings, but in a large large app, every little bit helps.
Of course, my interpretation of this question, was looking at a Delphi exe in OllyDbg. I could be off base on where you guys were going with this topic, but I feel in regards to Olly and reversing, I am on point (if that was what you were talking about) lol.

Related

When and how should I obfuscate my Delphi code?

What should I know about code obfuscation in Delphi?
Should I or shouldn't I do it?
How it is done and is there any good tools (commercial/free) to automate it?
Why would you need to?
As a whole Delphi does not decompile back, unlike .net, so, while decompilation is always a bit of a risk, Ive never found a decompiler that actually did it to a useful way, lots of areas got left as assembler and so on.
If people want to rework your work, they can, no matter what, obfuscation or not, heck, some coders write almost naturally obfuscated code (having worked with a few)
My vote therefore, is shouldnt bother. Unless someone can show me a decompiler for delphi that really works, and produces full sets of compilable, and all delphi where it was originally, I wouldnt worry one drop.
Pythia is a program that can obfuscate binaries (not the source) created with Delphi or C++ Builder. Source code for Pythia is here.
Before:
After:
There's no point obfuscating since the compiler already does that for you.
There is no way to re-create the source code from the binary.
And components can be distributed in a useful way without having to distribute the source code.
So there usually is no (technical) reason for distributing the source code.
You could do other things to reduce an attacker's ability to disable your software activation system, for example, but in a native-compiled system like Delphi, you can't recreate source code from the binaries. Another answer (the accepted one at the moment) says exactly this, and someone else pointed out a helpful tool to obfuscate the RTTI information that people might use to gain some insight into the internals of your software.
You could investigate the following hardening techniques to block modification of your system, if that's what you really want:
Self-modifying code, with gating logic that divides critical functions of your code such as software activation, into various levels of inter-operable checksums, and code damage and repair.
Debug detection. You can detect debuggers being used on your software and attempt to block the software from working in this case.
Encrypt the PE binary data on disk, and decrypt it either at load time, or just in time before it runs, so that critical assembler code can not be so easily reverse engineered back to assembly language.
As others have stated, hackers working on your software do not need to restore the original sources to modify it. They will attempt, if they try it at all, to modify your binaries directly, and will use a detailed and expansive knowledge of assembler language to circumvent things you may wish them not to.
You can use free JCF (Jedi Code Formatter) to obfuscate your source code. However, pascal syntax does not allow strong obfuscation and JCF even doesn't do it's best (well, it's a code formatting tool, not obfuscator!)

Delphi decompiling [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Why decompiling a delphi exe, is so easy, compared to others executables built with other programming languages/compilers?
There are a few things that help with reversing delphi programs:
You get the full form data including the name of event handler methods
All members with published visibility have metadata used with RTTI
The compiler is pretty bad at optimizing. It does no whole program optimization and the assembly is usually a straight forward translation of the original source with only minor optimizations. (At least it was in the versions I used, might have improved since then)
All classes, even those compiled with RTTI off have some level of metadata available. In particular it's possible to get the name and inheritance structure of classes. And for any instance of a class you happen to see in the debugger you can get its VMT and thus its class name.
Delphi uses textfiles describing the content of your form and hooks up event handlers by name. This approach obviously needs enough metadata to deserialize that textual representation of a from and hook up the eventhandlers by name.
An alternative some other GUI toolkits use is auto-generating code that initializes the form and hooks up the event handler with code. Since this code directly uses pointers to the eventhandlers and directly assigns to properties/calls setters it doesn't need any metadata. Which has the side-effect that reversing becomes a bit harder.
It shouldn't be too hard to create a program that transforms a dfm file into a series of hardcoded instructions that creates the form instead. So a tool like DeDe won't work that well anymore. But that doesn't gain you much in practice.
But figuring out which evenhandler corresponds to which control/event is still rather easy. Especially since stuff like FLIRT identifies most library functions. So you just need to breakpoint the one you're interested in and then step into the user code.
The statement you make is false. Delphi is not particularly more easy to decompile than code produced by other mainstream compilers.
For .net languages there is Reflector.
C++ is covered in this Stack Overflow question.
Python/Perl/Ruby etc. are interpreted.
If you were able to prove that the results of decompiling a Delphi executable were of significantly higher quality than in other widely used languages then your question would carry more weight.
Story from the trenches: Decompiling a tiny Delphi DLL
I've been through a Delphi decompiling session myself. It was one of those fake-sounding "I lost my sources" thing, I really did lose the sources for a tiny Firebird UDF library. Now I do no better, I didn't jump right into decompiling because the library was so small and I knew a rewrite would be much faster.
This DLL exports a function that looks like this:
function udf_do_some_math(Number1, Number2:Currency): Currency;
After doing the sane thing and rewriting the function and doing some regression tests I discovered some obscure corner-cases where the new function's result wasn't the same as the old function's result! The trouble was, the new function's result was the correct result, the old DLL contained a BUG and I had to reproduce the BUG - with this function consistency is more important then accuracy.
Again, did the sane thing and tried to "guess" at the BUG. I knew it was a rounding issue but simply couldn't figure out what it was. Finally I decided to give decompilers I try. After all this was a small library, the entry-point was straight-forward and I didn't really need re-compilable code, nor 100% decompilation: I only needed enough to figure out the old BUG so I can reproduce it!
Decompiling failed! I tried lots of different decompilers, including a couple of "commercial" ones. Most produced what on the surface looked like good data, but not enough to figure out the old bug. The most promising one, the one with version specific knowledge of the VCL and RTL gave the worst failure: sure, it figured out the RTL calls, gave them names, but failed to locate the exported function! The one function I was interested in wasn't shown int the list of entry points, and it should have been straight forward since it's an exported function.
This decompiling attempt should have been easy because:
The code was fairly simple and not a lot of it.
It was a DLL with an exported function, none of the complexity you'd expect from an event-driven exe.
I wasn't interested in re-compilable code, I simply wanted to find an old bug so I can reproduce it.
I didn't ask for Pascal code, assembler would've been good enough.
I knew precisely what the code was doing and how it was doing it. It wasn't cryptic 3rd party code.
My solution
After decompilers failed me I turned to my own trusty Delphi IDE for debugging. I wrote a small Delphi program that directly imports the function from the DLL, created a fake Firbird memory manager DLL so my DLL can load, called my old function with the parameters I knew would give bad results, steped into the code using the debugger and closely watched the FPU registers. After a few failed attempts I finally noticed a value was popped from the FPU stack as integer where it shouldn't have been Integer so I had my BUG: I mistakenly defined an Integer local variable where I should have used Currency. Armed with that knowledge I was able to reproduce the bug.
Only thing that is easier in Delphi is retrieving VCLs.
After using decompilers like DeDe you will get application user interface but without any logic.
So if you want to retrieve only forms and buttons - Delphi is easier than other compilers, but if you want to know what is going on after clicking on the button you'll need to use ollydbg or other (debugger/disassembler) as for other languages that creates executables.
There are pros and cons. I am not sure what angle your referring to as being easier. There is also a huge difference in a 1 form simple application, versus a very in-depth application that has many forms and tons of classes and functions. It's like Notepad versus Office 2013 (given they were coded in delphi, just an example comparing complexity not language).
In a small app, having the extra information that Delphi apps "usually" contain can make it a breeze. However, in a large application it may "help", but you have a million calls to dig through. They may help you get in the near vicinity, but calls inside of calls inside of calls, then multiple returns used as jumps... makes you dizzy. Then if the app "was" packed or protected, some things can still be a garbled mess. While it may work programming wise, reading it can be a lot harder. I was in one the other day, where all of the strings were encrypted, so "referenced text strings" were no help, and the encryption was not a simple md5 or base64, it was some custom algorithm. Maybe an MD5 with a salt, then base64 encoded? I never could get to the exact method on the strings. I knew what some of them were supposed to be, but couldn't reproduce the method, even though it looked like it was base64, it was the base64 of the string already encrypted some how... I dont rely on text strings, but in a large large app, every little bit helps.
Of course, my interpretation of this question, was looking at a Delphi exe in OllyDbg. I could be off base on where you guys were going with this topic, but I feel in regards to Olly and reversing, I am on point (if that was what you were talking about) lol.

Is an update to D2010 really meaningful

I am trying to migrate my own projects to delphi 2010. But it seems to be very difficult.
I use TntControls for old projects. If I remove this library, some runtime functions must be re-implemented by myself. For instance: convert UnicodeString to a specified code page.
The "SizeOf", "Length", FillChar() still confuse me. Compiler will throw a warning, if SizeOf() should be replaced with Length(). But I have not found any idiot-safe tutorials for me.
A confusing warning, when trying to cast an AnsiString to UnicodeString. This conversation won't cause a data lose, will it?
Many code (zip, string utils, etc.) must be retested.
Too many headaches... Can someone share experience on migrating existing project from a very old delphi to delphi 2010?
conversion Unicode string to specified code page with only Delphi: Simpler than ever. Thanks to the String class ability to create a string of a desired codepage, and convert cleanly from one codepage to another.
FillChar is bytes, not characters, name is now unfortunate. Not that confusing really.
That warning is there to make you think, which it did. Job done.
Oh yes. But that retesting and re-reading has been the biggest benefit for me.
I have migrated all my projects to Delphi 2009/2010 and found the benefits included:
A. a thorough re-reading of my code brought many ways I needed to clean it up (because it's a bloated old mass of accidents and incremental code-sludge, like most RAD/delphi projects end up), few of which are purely unicode or port related, but all of which made the products better for being forced through the changes.
B. a cleaner world, with fewer third-party components. Dropping TNT, and a dozen or two third party components will make your project smaller, more orthogonal and easier to support.
C. There's no reason in porting to make it one way. None of my project ports are actually "moved" permanently into Delphi 2009/2010. They all build in both worlds just fine. I use the type UnicodeString widely in all my code wherever I need it, and I make a typedef to WideString, when compiling on Delphi 2007 or older versions.
D. The delphi 2010 ide works great on Windows Vista and Windows 7, and the language is a joy to work with. Delphi 2009 and 2010 don't crash, which Delphi 2007 and Delphi 7 often do for me.
If you don't need to support Vista and Win7, and you're 100% happy and glitch-free running TNT components, and your app doesn't make you money, then leave it where it is. If it makes you money, invest your time, and you will soon see the rewards. Delphi 2010 and 2009 are easily the best delphi versions ever, and the only major headache that remains is that the documentation has remained below the quality of Delphi 7 ever since they moved off WinHelp format help files.
If you're using Tnt and you're converting between code pages already, then yes, switching to Delphi 2010 will cause you extra work because you'll need to remove code for things that Delphi now handles intrinsically. Ultimately, your code will be simpler, but it will be a hassle to get it there in the meantime.
SizeOf, Length, and FillChar are very basic concepts that you, as a professional software developer, owe to yourself to understand. Be cognizant of whether you're dealing with character data or non-character data, and when dealing with the latter, don't use character-related types. You've got TBytes; use it. Don't use strings as byte buffers. When you want to know how many bytes you have, use SizeOf; when you want to know how many "things" you have, use Length. Generally avoid FillChar; you probably don't need it as much as you use it today anyway. Since the "char" that things are filled with is almost always zero anyway, you might consider using ZeroMemory instead. It has fewer parameters and is just as fast as FillChar, especially since Delphi supports function inlining.
The compiler warns you when converting from AnsiString to UnicodeString because it's not a simple string assignment but rather a conversion, guaranteed to allocate more memory and copy everything one character at a time. It's a performance warning, not a data-loss warning. Conversions in the opposite direction are both (even when assigning to Utf8String, which technically will never lose data from a UnicodeString, if it's filled only with valid Unicode characters). The best way to avoid the warning is to not use AnsiString in the first place. Use plain old String except for code that really does need to know what code page to encode things as.
I don't think the "retest" argument is very strong. The library code especially should have unit tests that you've been running every time you recompiled. Retesting is something you do several times a day; there's no special effort involved unless something goes wrong.

Is automated source translation seen as beneficial and/or necessary?

I have recently spent several years translating legacy FORTRAN into Java. Prior to that, I found myself translating FORTRAN into C (for which I wrote a simple translation tool). After all this work, I find myself wondering how many others are doing similar language-to-language translations and whether an automated way of doing so would be beneficial.
I know about F2C, For_C, F2J and others, as well as some of the translation sites, but none seem to be all that successful. Having seen output from For_C, I can see why it just hasn't taken off. While it is technically correct, it is very difficult to maintain.
So, I guess what I am wondering is if there were are tool that produced more maintainable, more grok-able code than the code I have seen, would developers use it? Or are developers as jaded as many posts seem to indicate and unwilling to use generated code as it could never be as good as their manually translated code?
In short, no. Obviously time restraints necessitate it sometimes, but...
Rarely is code written in one language going to translate well to another - every language has certain ways of doing things that are more suited to the constructs available / common libraries / etc.
Consider for example a program written in C as compared to something written in Python - certainly you can write for loops and iterate through things in Python just as easily as you can in C, but it is much simpler to use list comprehensions and take advantage of the features the language provides.
I'd be surprised to see an example of a reasonably sized program written in any language that could be translated into 'correct', well-maintainable code in any other.
This was already covered to some extent in Conversion of Fortran 77 code to C++, but I'll take a stab at it here.
I think there's a lot of time wasted translating legacy code to new languages. It takes a phenomenal amount of time and energy to do, and you introduce new bugs when you do it.
Joel mentioned why rewriting from scratch is a horrible idea in Things you Should Never do Part I, and though I realize that translating something to a new language isn't quite the same as rewriting from scratch, I claim it's close enough:
Automated translation tools aren't wonderful because you don't get anything maintainable out of them. You pretty much have to know the old code to understand the new code, and then what have you gained?
To port something manually, you have to know how the code works to do it well. Rewriting code is seldom done by the original developers, so you seldom get people who understand everything that's going on to do the rewrite. I worked at a company where an outsource team was hired to translate an entire website backend from ColdFusion to JSP. That project kept getting delayed and delayed because the port team didn't know the code at all. Our guys never quite liked their design, and they never quite got it right, so there was constant iteration as everyone worked out all the issues that were solved in the original code. Then, the porting itself took forever.
You also need to be familiar with really technical inconsistencies between languages. People who are very familiar with two languages are rare.
For Fortran specifically, I now work at a place where there are millions of lines of legacy Fortran code, and no one here is about to rewrite it. There's just too much risk. Old bugs would have to be re-fixed, and there are hundreds of man-years that went into working out the math. Nobody wants to introduce those kinds of bugs, and it's probably downright unsafe to do it.
Instead of porting, we have hybrid codes. After all, you can link Fortran and C/C++, and if you make a C interface around your Fortran code, you can call it from Java. Modern codes here have C/C++ components that make calls into old Fortran routines, and if you do it this way you get the added benefit that Fortran compilers are screaming fast, so the old code continues to run as fast as it ever did.
I think the best way to handle this is to do any porting you need to do incrementally. Make a lightweight interface around your old fortran code and call the pieces you need, but only port things as you need them in the new part. There are also component frameworks for integrating multi-language applications that can make this easier, but you can check out Conversion of Fortran 77 code to C++ for more on that.
Since programming is hard, no such tool can really exist.
If it was trivial to change one language into another, the idea of "compiler" would be moot. You'd just map the language you liked into the language of the hardware, press the button and be done.
However, it's never that simple. Each VM, each language, each API library adds nuances that are just impossible to automate.
" I can see why it just hasn't taken off. While it is technically correct, it is very difficult to maintain."
Correct for F2C as well as Fortran to machine language. The object code generated from most compilers can't easily be read by people. Either it's cruddy or it's highly optimized. Either way, it doesn't look a thing like an expert human would write in the assembler language for that hardware.
If only compiling could be reduced to some XSLT-like transformations that preserved the clarity of the old language in the new language. If there was only some universal Lingua Franca of computing that would be the Rosetta Stone of programming.
Until someone invents that Lingua Franca of computing, every language translation job will be hard and will lead to code that's "difficult to maintain" in the new language.
I've used f2c, and I agree with whoever wanted to name it cc2fc instead. It isn't a way of transforming Fortran into anything vaguely usable as C. It's a way of taking a C compiler and making a Fortran compiler out of it.
It did work just fine at taking that Fortran code and turning it (through C) to a Macintosh library I could call from Macintosh Common Lisp. Those were the days.

How to convert OWL/BP7 application to Delphi?

Which tool/approach would you suggest to convert of a large 16bit Windows GUI application, written in old Borland Pascal 7 / OWL, to Delphi?
Understanding the pretty heavy differences between OWL and VCL, as well as the differences between the pointer manipulations in 16bit pascal and the state-of-art using of strings and objects in Delphi - are there any ways/tools which could help to avoid almost complete rewrite of the application?
I think you need to determine;
a) how much of the code is to do with business logic, data(base) manipulation and things like proprietary file structures, mathematical processing etc? This is stuff that might lift largely 'as-is' because it's more likely to be written in 'pascal' with much smaller, obvious elements of OWL/BP7. For instance, when I did this with an application I had a series of units that dealt with loading/saving proprietary files, stuff to calculate easter, stuff to do maths on arrays etc - all of this stuff went from BP7 to Delphi (1) with almost no changes.
b) how much of the code is to do with the GUI (and nothing else) - message loop handlers, dialog element constructors, properities of controls etc. This stuff will take a lot of work to port to Delphi and unless you can find someone with a nice line in .RES->.DFM (or similar), I think you'll be looking at building this bit from scratch. No bad thing because if it's a 16bit Windows app then you'll probably want to take the opportunity to at least make it look a bit more 'modern' anyway. I think this will be the most labour-intensive part of the project.
c) how much of the code is using stuff that you know can be done differently in Delphi, but that would work as it stands in pascal right now? This is where #BloodySmartie's point about migrating to an older version of Delphi makes sense to me. You ought to be able to port that project to something like Delphi 5/7 making obvious (and well-understood) changes to things like string manipulation. The more of this stuff that you can leave unported, the better in my view. Get something that runs and that you check basic behaviour with, and then embark on a process of refactoring/refining to make the most of Delphi as and when the resources allow it. You might have (as I did) arrays of pointers in BP7, where each pointer goes to an array of pointers which ultimately lead to an object - this was how we got around memory limitations in the 16bit Windows world. When I first ported my app, these arrays of pointers to arrays of pointers still worked fine in Delphi and I left them alone until I had the time to do something more 'Delphi-like' with the structures.
But before you do all of that - why are you porting the app? If you're porting it because you're about to make a reasonable number of changes to the app's functionality anyway, then it might really be the right time to rewrite the app. As you're rewriting in Delphi, you are still going to be able to use chunks of functions and procedures that are business-rule based anyway, so it's not necessarily a complete and total rewrite from scratch.
I guess there is no tool to support your migration but i'd try to start in an old Delphi Version like 1,2 or 3. This syntax should be much nearer on BP7 than the syntax of newer Delphi Versions.
At this time, you should first try to just bring your app logic to delphi, without any visual stuff. Then use the form designer to rebuild your GUI.
A important point you should pay attention to is that a DOS string is an ASCII-String, while the Delphi strings up to Delphi 2007 are ANSI-encoded. In Delphi 2009, the string keyword describes a unicode string.
Long-long time ago when I swapped OWL to VCL (in C++) it was just easier to write everything from scratch. There might be some code parts that don't deal with user interface and string manipulations, but otherwise it's totaly different.
In fact one of my biggest app is still in OWL, because I just don't bother to rewrite it. As long as it works, let it be.
we also had - and still have - tons of owl-applications.
so we did port the 16bit owl to 32bit owl and are therefor still developing and maintaining our owl-based applications (actually with Delphi 2007 for win32).
you may find this way easier and faster than switch to vcl.
cheers
Andrej
FrameworkPascal.com provides an effective solution with minimal changes to the original windows 3.1 code. We did it for a while but now we provide a rounded solution with 32 bit compatible OWL units. We also provide with it ODBC SQL units, MAC address based security technology and special units CRT like units which can handle code written for DOS text and graphic modes mode, mixed, with and new 32 bit graphics and targeted at Windows 32/64 GUI applications. Legacy code can be which can be compiled with OWL Windows MDI starting with model applications demos which can be quickly modified.

Resources