I wrote a small C#/.Net application that is able to read the cookies.sqlite file of Firefox. Since I upgraded to Firefox 4 my application is not able to open the database file:
Executing the line "connection.Open();" (in the code sample below) there will be an execption that says:
"File opened that is not a database file. file is encrypted or is not a database"
This is my program code:
class Program
{
static void Main()
{
const string PATH_TO_DATABASE = #"C:\Users\Boris\Desktop\TEMP\cookies.sqlite";
const string CONNECTION_STRING = #"Data Source=" + PATH_TO_DATABASE;
if (!File.Exists(PATH_TO_DATABASE)) return;
using (SQLiteConnection connection = new SQLiteConnection(CONNECTION_STRING))
{
connection.Open();
using (SQLiteCommand command = new SQLiteCommand("SELECT id, name, host, path FROM moz_cookies", connection))
{
using (SQLiteDataReader read = command.ExecuteReader())
{
while (read.Read())
{
string id = read[0].ToString();
string name = read[1].ToString();
string host = read[2].ToString();
string path = read[3].ToString();
Console.WriteLine("ID: " + id);
Console.WriteLine("Name: " + name);
Console.WriteLine("Host: " + host);
Console.WriteLine("Path: " + path);
}
}
}
}
}
}
I am using the .Net Wrapper DLL for Sqlite v. 3.6.23.1.
The target framework of the application is .Net 2.0.
I was able to open the sqlite database without any problems using an application called SqliteExpert.
It would be great if anybody has an idea!
Regards,
Boris
Firefox 4.0 uses SQLite version 3.7.4. (To see this, download SQLite Manager and run select sqlite_version(); in the "Execute SQL" tab.)
It appears that v3.7.4 creates databases that can't be read by v3.6.23.1. I can't find this explicitly stated in the release notes, but it's clear from comparing the cookies.sqlite file to the file format documentation that the format has changed. Specifically, according to the documentation, byte 19 (0x13) should be 1, but that byte in the cookies.sqlite file is 2. As per the documentation:
If a value greater than 1 is read by
SQLite, then the library will refuse
to open the database.
Like the "write version" described
above, this field exists to facilitate
some degree of forwards compatibility,
in case it is ever required. If a
version of SQLite created in the
future uses a file format that may not
be safely read by older SQLite
versions, then this field will be set
to a value greater than 1.
To read the database, you will need to use the latest version of SQLite; unfortunately System.Data.SQLite hasn't been updated in almost a year. The project has since been taken over by sqlite.org, but downloads are not currently available.
If you don't want to wait for sqlite.org to release a v3.7.x-based .NET wrapper, you could try downloading the source and manually upgrading SQLite.NET/SQLite.Interop/src/sqlite3.c to the latest amalgamation C source file (available here).
EDIT: As noted by sdwilsh, Firefox 4.0 uses Write-Ahead Logging; as the description of that new journal mode states:
Thus, if an older version of SQLite
attempts to connect to an SQLite
database that is operating in WAL
mode, it will report an error along
the lines of "file is encrypted or is
not a database".
I had the same problem. Previously I used a Python script (with sqlite integration) to fetch up data from the cookies.sqlite and perms.sqlite files. The latter still works fine. Indeed, all of the other .sqlite files are readable ... except for cookies.sqlite and places.sqlite. Those two produce the "encrypted or is not a database" error.
Rather than hunt down an upgrade for Python (or sqlite3), I created a patch for the .sqlite files. This C-code changes the bytes at offset 18 and 19 from 2 to 1. I run this on Windows under Cygwin, but it should compile and run on Unix/Linux.
Warning: Don't do this to the original Firefox cookies.sqlite file.
Instead, copy that to a temp file, then run the patch on the copy.
// ffpatch.c
// Edits the specified Firefox .sqlite file.
// Changes 0x0202 to 0x0101 at offset 18/19.
// BEFORE
// 0000000 S Q L i t e f o r m a t 3 \0
// 0000020 004 \0 002 002 \0 # \0 \0 005 034 \0 \0 \0 N
// AFTER
// 0000000 S Q L i t e f o r m a t 3 \0
// 0000020 004 \0 001 001 \0 # \0 \0 005 034 \0 \0 \0 N
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#define PROGNAME "ffpatch"
#define MY_OFFSET 18
int main (int argc, char *argv[])
{
int fd;
char buf[2];
off_t offset;
ssize_t wsize;
if (argc != 2)
{
fprintf(stderr, "usage: %s sqlite-file\n", PROGNAME);
exit(1);
}
if ((fd = open(argv[1], O_RDWR)) == -1)
{
fprintf(stderr, "cannot open %s\n", argv[1]);
exit(1);
}
if ((offset = lseek(fd, MY_OFFSET, SEEK_SET)) != MY_OFFSET)
{
fprintf(stderr, "lseek() failed\n");
exit(1);
}
buf[0] = 1;
buf[1] = 1;
wsize = write(fd, buf, 2);
close(fd);
exit(0);
}
Hello and thanks alot for your answers!
I made my application work this way:
1.
I downloaded the sources of the current ADO.NET Connector for .NET 4.0 here: http://system.data.sqlite.org/index.html/timeline?r=trunk
Maybe you will have to logon on the website first using a anonymous user name and a capcha as passoword.
2.
I obtained the precompiled version of the sqlite3.dll v.3.7.4 by downloading an installing this ADO.NET connector: http://www.devart.com/dotconnect/sqlite/
(You may use the ADO.NET connector libs as an replacement for connector from system.data.sqlite.org as well.
I myself am only interested in the sqlite3.dll.)
3.
After compiling the sources from system.data.sqlite.org I copied the resulting System.Data.Sqlite.dll and the sqlite3.dll to my applications output directory. Please note that both DLLs are compiled either for x86 or x64 machines.
Regards
I think I got your problem. Your db connection is OK. First of all you are using which version of dotnetFramework? Accordingly you can download and use System.Data.SQLite.dll file to your references then your problem may be solved. I think you are using a System.Data.SQLite.dll file that is older one (doesn't match your version of dot net).
Related
txtStatus.Text = "";
if (!File.Exists(txtOpenLocation.Text))
{
txtStatus.Text = "File Not Found";
return;
}
txtStatus.Text = "File Found";
const string DLL_32BITS = "gsdll32.dll";
const string DLL_64BITS = "gsdll64.dll";
//select DLL based on arch
string NomeGhostscriptDLL;
if (Environment.Is64BitProcess)
{
NomeGhostscriptDLL = DLL_64BITS;
}
else
{
NomeGhostscriptDLL = DLL_32BITS;
}
GhostscriptVersionInfo gvi = new GhostscriptVersionInfo(NomeGhostscriptDLL);
var rasterizer = new GhostscriptRasterizer();
try
{
rasterizer.Open(txtOpenLocation.Text, gvi, true);
Console.WriteLine(rasterizer.PageCount); //This line always prints 0
} catch(Exception er)
{
txtStatus.AppendText("\r\nUnable to Load the File: "+ er.ToString());
return;
}
I have googled on it, but got no solution, and no helpful documentation about the rasterizer.Open() function.
The Console.WriteLine(rasterizer.PageCount); always prints 0, regardless which pdf file I load.
txtStatusis a multiline TextBox in UI. txtOpenLocation is another TextBox in UI, non-editable by user, and its value is set by a OpenFileDialog.
I am using Visual Studio 2019 Community Edition.
Another observation I feel worth mentioning— for every pdf file on my machine, when I try to open any pdf file with either Adobe Acrobat DC or Foxit Reader, first the reader crashes, becomes 'not responsive' for about 10 to 15 seconds and then it opens the pdf file.
I had the same problem yesterday, I downloaded version 9.26 from here https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs926/gs926aw32.exe, and works!
I think this is a bug of ghostscript 9.27 release.
This isn't a bug at all, I suspect, (I certainly do not believe its a Ghostscript bug) but its probably a change in behaviour. Due to reported security vulnerabilities the Ghostscript developers have been removing access to many non-standard PostScript extensions (unique to Ghostscript). Most recently access to the dictionary for processing PDF files has been secured.
My suspicion is that Ghostscript.NET (which is not maintained by the Ghostscript developers) is using one or more non-standard extensions to do the work of retrieving the count of pages. Without knowing what exactly is being used currently I can't be sure of course.
If the developer of Ghostscript.NET would like to contact us and confirm this is the problem then we can discuss the currently supported method for retrieving the count of pages in a PDF file.
It won't help at all to send me a project using Ghostscript.NET, since I don't know anything about it. I'm also not a C# or .NET developer, so the code would likely be meaningless to me.
Ghostscript returns considerable information on the back channel, stdout and/or stderr. These can be redirected to an application-defined data sink. I imagine that Ghostscript.NET will give you some means to retrieve these and if you plan to do any real development involving Ghostscript then I would very strongly reccomend that you find out how to get this information.
When you say 'no error is thrown from Ghostscript' I think you may be confusing Ghostscript and Ghostscript.NET. Without seeing the back channel from Ghostscript I don't see how you can tell if Ghostscript is generating an error.
NB if you plan to distribute your application you must abide by the terms of the AGPL version 3 (which is the license applying to Ghostscript), and that includes shipping a copy of the license, and some means for informing users where they can get the original.
As with the OP and the primary answer to this question, I too encountered this exact issue just yesterday.
I just want to add that for me the suggested version of ghostscript (9.26) wasn't working. It complained that I should be using a 64 bit version.
For those who need that, it's here: https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs926/gs926aw64.exe
I had to just guess at the URL. I'm amazed at how difficult it has been to find older versions.
This issue has been fixed in the latest release v.1.2.2 of GhostScript.NET
The fix was to stop using pdfdict and GS_PDF_ProcSet if the version was over 9.26 as these two functions were made private by the Ghostscript team for security reasons.
I am not very familiar with GhostScript or PostScript, however, I have traced down the issue within the GhostScript.NET code, which uses the gsapi to execute functions. The function that is being executed and failing on gs is within file GhostscriptViewerPdfFormatHandler.cs on the GhostScript.NET Project.
Upon further testing through using both a gs9.26 as recommended by Oswaldo Cotes Solano and comparing the results with gs9.52 using a test script, I have found that GS_PDF_ProcSet is causing a Unrecoverable error, exit code 1 on gs 9.52.
This leads to failure while using the gs9.52 API, however, it is by design since gs9.27 to add security. While -dNOSAFER is not recommended for production ready applications, it will get us by.
An example of the intended execution and result that works in gs9.26 should be similar to:
gswin32c.exe -q -dNOSAFER -sPDFname=c:/pdfs/test.pdf c:/pdfs/pdfpagecount.ps
Executing:
/GSNETViewer_PDFpage {
(%GSNET_VIEWER_PDF_PAGE: ) print dup == flush
pdfgetpage /Page exch store
Page /MediaBox pget
{ (%GSNET_VIEWER_PDF_MEDIA: ) print == flush }
if
Page /CropBox pget
{ (%GSNET_VIEWER_PDF_CROP: ) print == flush }
if
Page /Rotate pget not { 0 } if
(%GSNET_VIEWER_PDF_ROTATE: ) print == flush
} def
Executing:
/Page null def
/Page# 0 def
/PDFSave null def
/DSCPageCount 0 def
Executing:
GS_PDF_ProcSet begin
pdfdict begin
Executing: (C:/pdfs/Output.pdf) (r) file runpdfbegin
Executing: /FirstPage where { pop FirstPage } { 1 } ifelse
Executing: /LastPage where { pop LastPage } { pdfpagecount } ifelse
Executing: flush (%GSNET_VIEWER_PDF_PAGES: ) print exch =only ( ) print =only (
) print flush
%GSNET_VIEWER_PDF_PAGES: 1 1
Executing: process_trailer_attrs
Executing: 1 GSNETViewer_PDFpage
%GSNET_VIEWER_PDF_PAGE: 1
%GSNET_VIEWER_PDF_MEDIA: [0.0 0.0 612.0 792.0]
%GSNET_VIEWER_PDF_CROP: [0.0 0.0 612.0 792.0]
%GSNET_VIEWER_PDF_ROTATE: 0
Executing: Page pdfshowpage_init pdfshowpage_finish
Loading NimbusSans-Regular font from %rom%Resource/Font/NimbusSans-Regular... 4124032 2548352 5183568 3818848 3 done.
showpage, press <return> to continue
While running 2.52 with -dNOSAFER and also adding the -dNOSAFER argument to CLI to avoid the file access error, and the GhostScript.NET source to allow for the same functionality. Although the -dNOSAFER option is not the ideal choice and may have vulnerabilities, to test without diving further in, I've used this method for testing.
C:\Program Files\gs\-\bin>gswin64c.exe -q -dNOSAFER -sPDFname=test.pdf c:/pdfs/pdfpagecount.ps
Error: /undefined in GS_PDF_ProcSet
Operand stack:
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval--
Dictionary stack:
--dict:738/1123(ro)(G)-- --dict:0/20(G)-- --dict:84/200(L)--
Current allocation mode is local
Current file position is 992
GPL Ghostscript 9.52: Unrecoverable error, exit code 1
Ultimately making a minor change 3 locations of the source has resulted in a working solution with 9.52. I'll do a pull-request with our changes and update the community when a pull request has been issued, otherwise, you can make a pull directly to our fork.
I've had the same problem. I was using c# (.NET) Ghostscript.NET (version 1.2.3). Problem was PDF file name. If it had parenthesis ) or (, then that problem occurs.
I had to rename PDF file in order to escape those characters.
using Ghostscript.NET.Rasterizer;
var strFilePath = "C:\PdfFile(.pdf";
using (var rasterizer = new GhostscriptRasterizer())
{
rasterizer.Open(strFilePath);
var strPageCount = rasterizer.PageCount; //return 0
}
var pattern = "[^A-Za-z0-9 .-]+";
var regEx = new Regex(pattern);
strFilePath = regEx.Replace(strFilePath, "");
using (var rasterizer = new GhostscriptRasterizer())
{
rasterizer.Open(strFilePath);
var strPageCount1 = rasterizer.PageCount; //return number of pages
}
enter image description hereI am using a C# dll using pythonnet on python 2.7.13 (which uses other dll files and .mdb database files) to make some technical calculations. This dll files does not have a good documentation (only namespaces, class and method names). Well the program in most PC Works Fine but in all office computers it throws a runtime Error from Dll files (my doubt is connection with database). This dll files are compiled to target .NET 4.0 (in office computers is installed .NET 4.7.1 or other versions newer than 4.0) and EntityFramework is also being used (programs target 5.0 and this is a dll file in program folder, but in office computers is installed EntityFramework 6.2 tool). Microsoft database Engine 2010 is also installed in those computers.
In every other computer that I have tested the program it works perfectly. In office computers I found a group of input data for which program works, but anyway this is not correct because it should work also for the default data.
To make tests in office computers I have compiled python code using PyInstaller (I repeat, compiled version work fine in other PCs).
I am using .NET Reflector to decompile dll files and programs Exception to find the Error. The method that throws Exception is in the following code.
Thanks in advance!
public int LoadRanghiAmmessi(int[] vRanghi, string geometria)
{
int index = 0;
CrConnection connection = new CrConnection(this.PathDB);
string query = "SELECT * FROM RanghiAmmessi WHERE (Geometria='" + geometria + "') ORDER BY NRanghi";
OleDbDataReader recordset = connection.GetRecordset(query, #"\Coils.mdb;");
if (!recordset.HasRows)
{
if (recordset != null)
{
recordset.Close();
}
query = "SELECT * FROM RanghiAmmessi WHERE (Geometria='*') ORDER BY NRanghi";
recordset = connection.GetRecordset(query, #"\Coils.mdb;");
while (recordset.Read())
{
vRanghi[index] = int.Parse(recordset["NRanghi"].ToString());
index++;
}
if (recordset != null)
{
recordset.Close();
}
}
return index;
}
public OleDbDataReader GetRecordset(string query, string NomeDB)
{
string connectionString = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + this.PathDB + NomeDB + "Jet OLEDB:Database Password=123456";
this.ChiudiConnessioni();
this.conn = new OleDbConnection(connectionString);
OleDbCommand command = new OleDbCommand(query, this.conn);
try
{
this.ApriConnessione();
return command.ExecuteReader();
}
catch (Exception exception)
{
exception.Message.ToString();
this.ChiudiConnessioni();
return null;
}
}
After many tests I found out that the program is working also in other PC after declaring some objects like function parameters and after compiling running the program as compatible with Windows 7. Before the objects were created like variables and those variables were passed as parameters, (in this case, reasonably the first thought is that the problem is "pass by reference" mechanism and that some values are not inserted in the right mode, but this is not the case because:
- the same exactly code did function very well in most PC (compatibility
problem)
- the same exactly mechanism is used to specify the objects attributes and
to make calculations
In this conditions I would say that it is not clear where the problem was. In the first version installing the SQL Server Express made possible for the program to work well even without last modifications.
Umm... given the details that it works fine on "Other PC", I am guessing that the problem is your so-called database. I don't see in any way, however, how anyone could be certain at what the problem is until it is solved.
I'm working on a C# application that has to read an Access database (.mdb), on Linux. I'm using Mono to compile and run the application.
Suppose I have a test database that I create in Access 2013. It has one table: TestTable, with the default ID column and a testField1 column created with the 'Long Text' type. I insert three rows, with these values for the testField1 column: "foo", "bar", "baz". The database is saved as 'Access 2002-2003 Database (*.mdb)'.
The resulting database (named Test.mdb) is transferred to my Linux box. Just as a sanity check, I can run mdb-export on the database:
$ mdb-export Test.mdb TestTable
ID,testField1
1,"foo"
2,"bar"
3,"baz"
So far, so good. Now, suppose we have a C# program that reads the testField1 column of the table:
using System;
using System.Data.Odbc;
class Program {
public static void Main(string[] args){
try {
OdbcConnection conn = new OdbcConnection("ODBC;Driver=MDBTools;DBQ=/path/to/Test.mdb");
conn.Open();
var command = conn.CreateCommand();
command.CommandText = "SELECT testField1 FROM TestTable";
var reader = command.ExecuteReader();
while(reader.Read()){
Console.WriteLine(reader.GetString(0));
}
} catch(Exception e){
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
I would expect that running this program would print "foo", "bar", and "baz". However, compiling and running the program does not yield this output:
$ mcs mdb_odbc.cs -r:System.data.dll
$ mono mdb_odbc.exe
潦o
$ # this line added to show the empty lines
My guess is that this is an encoding issue, but I have no idea how to resolve it. Is there a way to fix my program or the environment that it runs in so that the contents of the database are printed correctly? I believe that it is an issue with either ODBC or MDBTools, because in a similar program, a string equality check against fields of a database fails.
I'm using Ubuntu 16.10. mono --version outputs Mono JIT compiler version 5.4.0.167 (tarball Wed Sep 27 18:38:59 EDT 2017) (I built it from source with this patch applied to fix another issue with ODBC). MDBTools, installed through Apt, is version 0.7.1-4build1, and the odbc-mdbtools package is the same version.
I know that the combination of tools and software I'm using is unusual, but unfortunately, I have to use C#, I probably have to use Mono, I have to use an Access database, and I have to use ODBC to access the database. If there's no other way around it, I suppose I could convert the database to another format (SQLite comes to mind).
I have a gem, roundhouse, which is an application compiled with .NET (C#). Runs on Windows and it should run in a 32 bit process.
To set up my gemspec, I set:
Gem::Specification.new do |s|
s.platform = 'mswin32'
s.name = 'roundhouse'
s.version = version
s.files = Dir['lib/**/*'] + Dir['bin/**/*']
s.bindir = 'bin'
s.executables << 'rh.exe'
When I install the gem, I should be able to type rh.exe from the command line at any path and it should run correctly.
In practice, I'm not seeing this work correctly. This is what I'm getting back:
Window has this for the header: 16 bit MS-DOS Subsystem
C:\WINDOWS\system32\cmd.exe - rh.exe
The NTVDM CPU has encountered an illegal instruction.
CS:xxxx IP:xxxx OP:xx xx xx xx xx Choose 'Close' to terminate the application.
Here is a picture of the issue (link to TwitPic): Error
If I go to the directory where the item was installed, I can run it and it works great. It's just something in the registration of the command to run from anywhere.
I did quite a bit of searching before asking and came up with nothing. It could be that I don't know what I should be searching for. So let me ask the question, is there a way to register an executable with gems for windows executable applications (built with .NET) and have them register properly with the command line? If so, how is that done?
UPDATE:
I found that gems creates a shim in the C:\Ruby\bin directory that points back to the other file. So there is a rh.exe file that is really just a text file. This is its contents:
#!C:/Ruby/bin/ruby.exe
#
# This file was generated by RubyGems.
#
# The application 'roundhouse' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0"
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
version = $1
ARGV.shift
end
gem 'roundhouse', version
load Gem.bin_path('roundhouse', 'rh.exe', version)
if you're distributing it with the file "rh.exe"
then you'll want to create a file
bin/rh
s.executables << 'bin/rh'
then when it's installed gems will create an "rh.bat" file which runs ruby "bin/rh" essentially (as you've seen).
So within bin/rh put something like
result = system(File.dirname(__FILE__) + "/rh.exe" ARGV.join(' '))
exit 1 unless result
result = system(File.dirname(__FILE__) + "/rh.exe " + ARGV.join(' '))
exit 1 unless result
So the endresult should maybe look like? note the space after 'rh.exe'
I'm trying to detect console application from the list of the executables files installed on my computer.
How to implement it?
Every application has a "subsystem" (windows application, console application or library; specified to the linker as option, I think). How to detect it using only the executable file?
Are there alternative methods to detect the application characteristic? Additionally, are there any method for detecting the file is a really executable file?
Any issue for JAR executables?
Without any programming you receive this information from
dumpbin.exe /headers filename
Some information gives you GetBinaryType and SHGetFileInfo functions. All information which you needs you will find in the header of every executable file. See Microsoft Portable Executable and Common Object File Format Specification in http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx.
One can use also Debug Help Library API from DbgHelp.dll (see http://msdn.microsoft.com/en-us/library/ms679309(VS.85).aspx). IMAGE_DOS_HEADER, IMAGE_DOS_SIGNATURE and IMAGE_NT_HEADERS32 structures gives you full information.
UPDATED (add some code):
Or you can use only structures defined in WinNT.h. The corresponding code can start like following
// Open source file
hSrcFile = CreateFile (pszSrcFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hSrcFile == INVALID_HANDLE_VALUE)
__leave;
// Map the source file in memory
hMapSrcFile = CreateFileMapping (hSrcFile, NULL, PAGE_READONLY, 0, 0, NULL); // SEC_IMAGE
if (!hMapSrcFile || hMapSrcFile == INVALID_HANDLE_VALUE)
__leave;
// Map the entire of the source file is memory
pSrcFile = (PBYTE) MapViewOfFile (hMapSrcFile, FILE_MAP_READ, 0, 0, 0);
if (!pSrcFile)
__leave;
pDosHeader = (IMAGE_DOS_HEADER *)pSrcFile;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
printf ("it is not a EXE file.\n");
return 1;
}
printf ("IMAGE_DOS_HEADER size %d (0x%X) bytes\n", sizeof(IMAGE_DOS_HEADER), sizeof(IMAGE_DOS_HEADER));
DumpDosHeader (pDosHeader);
pDosExeStart = (PBYTE)pDosHeader + pDosHeader->e_cparhdr*16;
if (g_bDump)
HexDump (1, pDosExeStart, pDosHeader->e_lfanew - pDosHeader->e_cparhdr*16, (DWORD)pDosExeStart);
if (pDosHeader->e_lfanew) {
IMAGE_NT_HEADERS32 *pNtHeader = (IMAGE_NT_HEADERS32 *)((PBYTE)pDosHeader + pDosHeader->e_lfanew);
//IMAGE_NT_HEADERS64 *pNtHeader64 = (IMAGE_NT_HEADERS64 *)((PBYTE)pDosHeader + pDosHeader->e_lfanew);
IMAGE_SECTION_HEADER *pFirstSectionHeader = (IMAGE_SECTION_HEADER *)((PBYTE)&pNtHeader->OptionalHeader +
pNtHeader->FileHeader.SizeOfOptionalHeader);
if (pNtHeader->Signature == IMAGE_NT_SIGNATURE) {
int i;
printf ("\nPE signature\n");
printf ("\nIMAGE_FILE_HEADER: size %d (0x%X) bytes, offset from the begin of the file: %d (0x%X)\n",
sizeof(IMAGE_FILE_HEADER), sizeof(IMAGE_FILE_HEADER),
((PBYTE)&pNtHeader->FileHeader - (PBYTE)pDosHeader), ((PBYTE)&pNtHeader->FileHeader - (PBYTE)pDosHeader));
DumpFileHeader (1, &pNtHeader->FileHeader);
switch (pNtHeader->OptionalHeader.Magic) {
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
printf ("\nIMAGE_OPTIONAL_HEADER32: size %d (0x%X) bytes, offset from the begin of the file: %d (0x%X)\n",
sizeof(IMAGE_OPTIONAL_HEADER32), sizeof(IMAGE_OPTIONAL_HEADER32),
((PBYTE)&pNtHeader->OptionalHeader - (PBYTE)pDosHeader), ((PBYTE)&pNtHeader->OptionalHeader - (PBYTE)pDosHeader));
DumpOptionalHeader32 (1, &pNtHeader->OptionalHeader);
break;
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
break;
case IMAGE_ROM_OPTIONAL_HDR_MAGIC:
break;
}
To determine the subsystem you need to read the executable file and parse the PE-Header. A detailed article on how to do that is found here.
A JAR file is just a ZIP file with some specific files and folder structure so you can open it like a regular zip file and look for those files and folders that are always there.
Windows PE executables have a field in the header that specify the subsystem (Console, GUI, Posix, and so on). They also have fields that can be used to identify executables in general. Download the PE specification from msdn.com to get the details.
It's possible to detect subsystem type using PeNet library, for example change see:
using PeNet;
...
var file = new PeFile(<path>);
if (file.ImageNtHeaders.OptionalHeader.Subsystem == 2 /*PeNet.Header.Pe.SubsystemType.WindowsGui*/)
{
// This is UI executable...
}
See also similar commit.
Use 0.5.0 version to get less dependencies, or use latest to get latest version.