Solved

Convert GUI app into console app for Win32 Env

Posted on 2016-10-03
5
55 Views
Last Modified: 2016-10-18
Hi all!,
 I was wondering if anyone out there would be willing and would be so kind to give me some pointers or to help me convert a GUI C++ program into a console (CMD.exe) style application that will run on a Windows XP box...

The program that i am looking or hoping to convert can be found at the following link :
 http://www.codeproject.com/Articles/577445/Querying-Wireless-Settings-and-Decrypting-Wireless

I have no idea what i am doing in C as i have only ever used Delphi 4, Delphi 6, VB3, VB6, PHP, Javascript and HTML (but as you would have gathered by that, i have a reasonable understanding of programming principles)

anyhow, i will leave it at that and i will be eagerly awaiting a reply from anyone :)
0
Comment
Question by:Jai Sewell
  • 3
5 Comments
 
LVL 25

Accepted Solution

by:
Sinisa Vuk earned 500 total points
Comment Utility
No need to convert ... because someone already make great source for this...
So... what I did is get wlan api from here (another great source for windows api is Jedi lib)
...add some changes ... and get this....
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, nduWlanAPI, Tlhelp32;

const
  WLAN_PROFILE_GET_PLAINTEXT_KEY = $00000004;
  CRYPT_STRING_HEX = $00000004;

const
  CRYPTPROTECT_LOCAL_MACHINE = 4;

type
  TLargeByteArray = array [0 .. Pred(MaxInt)] of byte;
  PLargeByteArray = ^TLargeByteArray;

  _CRYPTOAPI_BLOB = record
    cbData: DWORD;
    pbData: PByte;
  end;

  DATA_BLOB = _CRYPTOAPI_BLOB;
  PDATA_BLOB = ^DATA_BLOB;

type
  _CRYPTPROTECT_PROMPTSTRUCT = record
    cbSize: DWORD;
    dwPromptFlags: DWORD;
    hwndApp: HWND;
    szPrompt: PWideChar;
  end;

  CRYPTPROTECT_PROMPTSTRUCT = _CRYPTPROTECT_PROMPTSTRUCT;
  PCRYPTPROTECT_PROMPTSTRUCT = ^CRYPTPROTECT_PROMPTSTRUCT;

type
  TForm2 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

function CryptStringToBinaryA(pszString: LPCSTR; cchString: DWORD;
  dwFlags: DWORD; ppBinary: PBYTE; var ppcbBinary: DWORD;
  ppdwSkip: PDWORD; pdwFlags: PDWORD): BOOL; stdcall; external 'Crypt32.dll';

function CryptUnprotectData(pDataIn: PDATA_BLOB; ppszDataDescr: PLPWSTR;
  pOptionalEntropy: PDATA_BLOB; pvReserved: Pointer;
  pPromptStruct: PCRYPTPROTECT_PROMPTSTRUCT; dwFlags: DWORD; pDataOut: PDATA_BLOB): BOOL; stdcall; external 'Crypt32.dll';

implementation

{$R *.dfm}

function EnablePrivilege(name: String; Enable: boolean = true): boolean;
var
  hToken: THANDLE;
  priv: TOKEN_PRIVILEGES;
begin
  priv.PrivilegeCount:= 1;
  priv.Privileges[0].Attributes:= 0;
  if Enable then priv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
  LookupPrivilegeValue(nil, PCHAR(name), priv.Privileges[0].Luid);
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  AdjustTokenPrivileges (hToken, FALSE, priv, sizeof(priv), nil, PDWORD(nil)^);
  Result:= (GetLastError = ERROR_SUCCESS);
  CloseHandle (hToken);
end;
 
function GetProcessId(FileName: String): DWORD;
var
   proc: TProcessEntry32;
   hSysSnapshot: THandle;
begin
   proc.dwSize := SizeOf(TProcessEntry32);
   hSysSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   if (hSysSnapshot <> INVALID_HANDLE_VALUE) and Process32First(hSysSnapshot, proc) then
   begin
     repeat
       if String(proc.szExeFile) = FileName then
       begin
         Result:= proc.th32ProcessID;
         break;
       end;
     until not (Process32Next(hSysSnapshot, proc));
   end;
   CloseHandle(hSysSnapshot);
end;

function ImpersonateToLoginUser: BOOL;
var
  hProcess, hToken: THANDLE ;
  ID: DWORD;
begin
  Result:= false;
  ID:= GetProcessID ('winlogon.exe');
  if ID > 0 then
  begin
    hProcess:= OpenProcess (MAXIMUM_ALLOWED, FALSE, ID);
    if hProcess <> INVALID_HANDLE_VALUE then
    begin
      Result:= OpenProcessToken(hProcess, MAXIMUM_ALLOWED, hToken);
      if Result then
      begin
        EnablePrivilege('SeDebugPrivilege');
        Result:= ImpersonateLoggedOnUser(hToken);
        CloseHandle(hToken);
      end;
      CloseHandle (hProcess);
    end;
  end;
end;

function ExtractKey(XMLText: String): String;
var
  ini, fin: integer;
begin
  Result:= '';
  ini:= Pos('<keyMaterial>', XMLText);
  fin:= Pos('</keyMaterial>', XMLText);
  if (ini <> -1) and (fin <> -1) then
  begin
    ini:= ini + Length('<keyMaterial>');
    Result:= Copy(XMLText, ini, fin-ini);
  end;
end;

function DecryptData(Key: String): String;
var
  Buffer: array [0..1023] of BYTE;
  Len: DWORD;
  DataIn, DataOut: DATA_BLOB;
  pbuf: PByte;
begin
  Result:= Key;
  Len:= 1024;
  ImpersonateToLoginUser;
  if CryptStringToBinaryA(PCHAR(Key), Length(Key), CRYPT_STRING_HEX, @Buffer[0], Len, 0, 0) then
  begin
    DataIn.cbData:= Len;
    DataIn.pbData:= @Buffer[0];
    DataOut.cbData:= 0;
    DataOut.pbData:= nil;
    if CryptUnprotectData (@DataIn, nil, nil, nil, nil, 0, @DataOut) then
      Result:= PCHAR(DataOut.pbData);
  end;
  RevertToSelf;
end;

function WifiGetPassWords: String;
var
  hClient: THandle;
  dwVersion: DWORD;
  pInterfaceInfoList: Pndu_WLAN_INTERFACE_INFO_LIST;
  pInterfaceGuid: PGUID;
  pProfileList: Pndu_WLAN_PROFILE_INFO_LIST;
  pstrProfileXml: PWCHAR;
  dwFlags: DWORD;
  dwGrantedAccess: DWORD;
  i,j: integer;
begin
  Result:= '';
  dwFlags:= 0;
  dwGrantedAccess:= 0;

  if ERROR_SUCCESS = WlanOpenHandle(1, nil, @dwVersion, @hClient) then
  begin
    if ERROR_SUCCESS = WlanEnumInterfaces(hClient, nil, @pInterfaceInfoList) then
    begin
      for i:= 0 to pInterfaceInfoList^.dwNumberOfItems - 1 do
      begin
        pInterfaceGuid:= @pInterfaceInfoList^.InterfaceInfo[pInterfaceInfoList^.dwIndex].InterfaceGuid;
        if ERROR_SUCCESS = WlanGetProfileList(hClient, pInterfaceGuid, nil, @pProfileList) then
        begin
          for j:=0 to pProfileList.dwNumberOfItems-1 do
          begin
            dwFlags:= WLAN_PROFILE_GET_PLAINTEXT_KEY;
            if ERROR_SUCCESS = WlanGetProfile(hClient,	pInterfaceGuid, pProfileList.ProfileInfo[j].strProfileName, nil, @pstrProfileXml, @dwFlags, @dwGrantedAccess) then
            begin
              Result:= Result + String(pProfileList.ProfileInfo[j].strProfileName) + ': '+ DecryptData(ExtractKey(String(pstrProfileXml))) + #13 + #10;
              WlanFreeMemory(pstrProfileXml);
            end;
          end;
        end;
        WlanFreeMemory(pProfileList);
      end;
      WlanFreeMemory(pInterfaceInfoList);
    end;
    WlanCloseHandle(hClient, nil);
  end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Edit1.Text := WifiGetPassWords;
end;

Open in new window


... hope you'll need this for a good cause....
1
 

Author Comment

by:Jai Sewell
Comment Utility
That works quite well but is not quite there yet...

I would like to decrypt the hex code in the windows xp registry that stores the saved wifi password, however this cannot be decrypted to a clear text ascii value, i know for certain that it can be converted to a 64 part hexadecimal value (just like NirSoft's WirelessKeyView does), i will paste up a whole heap of stuff i have gathered together in an attempt to demonstrate what i mean...

the follow hex is converted to the 64 part hex :
C8 02 00 00 03 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 74 65 73 6C 61 73 6F 75 72 63 65 73 2E 63 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 65 B9 D7 BE 1C D2 01 03 00 00 80 00 00 00 00 01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB 01 00 00 00 7A 4F 87 A7 63 9A 26 4F AC C0 B7 DE 77 A5 22 66 00 00 00 00 02 00 00 00 00 00 03 66 00 00 A8 00 00 00 10 00 00 00 38 63 D1 60 FC 12 BD 00 DD 30 CD 0D 4D 3A 39 7A 00 00 00 00 04 80 00 00 A0 00 00 00 10 00 00 00 9F 9D F0 DB 34 EC B8 6F 8E BE 9E 82 A5 DC 1E 29 28 00 00 00 73 1C C6 88 7B 81 A1 2D 08 34 FA 6F B6 19 2B BD FF AF 44 E2 69 9D B8 A4 24 FE 7E 9D 8A 87 64 AB 71 59 74 A5 DA 28 2B C4 14 00 00 00 86 B6 8F D4 06 CA C4 B9 B5 83 84 78 55 F6 7D E0 A6 25 11 41

and the 64 part hex looks like :
fbf59171ee510db622f1a335a0dc86328b24cd7b12f705e4cb2cf72a0d496dfd

and the windows xp registry key is :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WZCSVC\Parameters\Interfaces\{32F9DEC7-9EC8-4972-A7D9-28C9624DD331}
0
 

Author Closing Comment

by:Jai Sewell
Comment Utility
Just run you're code again after i had the epiphany whilst laying in bed trying to get to sleep... to run the code with administrator privilege and it works bloody perfect!...
I must thank you Sinisa!.
And for anyone looking to use this code, it surely does work!, i used it in Delphi Enterprise 6 (6.163) on Windows 7 Ultimate 64bit... oooh and please also note that you will need an active wireless adapter, if you dont, then you simply wont get the codes (fully decrypted to i might add!, which far exceeded what i thought i would be able to accomplish, but please note that in WinXP it is impossible to fully decrypt the hex values from the registry to the original clear text password but you will get a 64 part hex value that you can use as the password instead, like WORD!, enter this 64 part hex value as the wifi password and you will be granted authorization and access!).

To start a Delphi app with escalated privilege by default (run as admin, simply by executing the app!, without changing "Compatibility settings/options" or right-clicking and selecting "Run as Administrator" ), please use the following code from stackoverflow post http://stackoverflow.com/questions/14703013/adding-manifest-for-admin-rights-request.

Create the following files uac.manifest, uac.rc, uac_xp.manifest and uac_xp.rc
Enter the code below for each file starting with uac.manifest, then uac.rc etc...

-uac.manifest

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="MyApp" type="win32"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

-uac.rc

1 25 "uac.manifest"

-uac_xp.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" name="MyApp" version="1.0.0.0" processorArchitecture="x86"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <!-- Windows Vista application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
       </security>
  </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--Windows 7-->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!--Windows Vista-->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
    </application>
  </compatibility>  
</assembly>

-uac_xp.rc

1 24 "uac_xp.manifest"


Now add the desired rc file (uac.rc or uac_xp.rc) to your project via the "Project > Add to project" menu item. This will create the {$R} directive in your project file:

program Project1;

{.$R 'uac.res' 'uac.rc'} // UAC only
// OR
{$R 'uac_xp.res' 'uac_xp.rc'} // UAC + XP Themes

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
0
 

Author Comment

by:Jai Sewell
Comment Utility
But this code does not work with WinXP as i had originally asked!, please note that people, if you try you get an error that says wlanapi.dll could not be found!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now