Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > ger.ct > #555049

Re: Onleihe

From Bonita Montero <Bonita.Montero@gmail.com>
Newsgroups ger.ct
Subject Re: Onleihe
Date 2022-05-18 08:30 +0200
Organization A noiseless patient Spider
Message-ID <t623pc$45g$1@dont-email.me> (permalink)
References <t3qqfg$2lh$1@dont-email.me>

Show all headers | View raw


Auf jeden Fall habe ich mal angenommen, dass Adobe Digital Editions
das PDF im Prozess-Adressraum liegen hat und ich es aus diesem aus-
lesen könnte. Da hab ich mir mal ein kleines Windows-Programm in
C++20 geschrieben das den Prozess-Adressraum nach einem Speicherblock
durchsucht der einen PDF-Header ("%PDF-*.*" - * steht für Versions-
nummer-Anteile) sowie einen PDF-Tailer ("%%EOF") enthält. Eigentlich
ganz einfach und hier ist der Code:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <vector>
#include <stdexcept>
#include <sstream>
#include <cctype>
#include <fstream>

using namespace std;

template<typename FilterFn>
	requires requires( FilterFn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( 
mbi ) } -> std::convertible_to<bool>; }
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess, 
FilterFn filterFn );
void savePdf( char const *header, size_t nBytes );

using XHANDLE = unique_ptr<void, decltype([]( HANDLE h ) { h && h != 
INVALID_HANDLE_VALUE && CloseHandle( h ); })>;

int main( int argc, char **argv )
{
	if( argc < 2 )
		return EXIT_FAILURE;
	try
	{
		DWORD dwProcessId = [&]() -> DWORD
			{
				DWORD dwRet;
				if( from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( 
argv[1] ), dwRet ); fcr.ec != errc() || *fcr.ptr )
					throw invalid_argument( "process-id unparseable" );
				return dwRet;
			}();
		XHANDLE hProcess( [&]() -> HANDLE
			{
				HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION | 
PROCESS_VM_READ, FALSE, dwProcessId );
				if( !hRet )
					throw system_error( (int)GetLastError(), system_category(), "can't 
open process" );
				return hRet;
			}() );
		vector<vector<MEMORY_BASIC_INFORMATION>> vvmbi = pageTree( 
hProcess.get(), []( MEMORY_BASIC_INFORMATION &mbi ) -> bool
			{
				return mbi.State == MEM_COMMIT;
			} );
		vector<char> processRegion;
		for( vector<MEMORY_BASIC_INFORMATION> const &vmbi : vvmbi )
			for( MEMORY_BASIC_INFORMATION const &vmbi : vmbi )
			{
				processRegion.resize( vmbi.RegionSize );
				if( !ReadProcessMemory( hProcess.get(), vmbi.BaseAddress, 
to_address( processRegion.begin() ), vmbi.RegionSize, nullptr ) )
					continue;
				char const *end;
				auto detectBegin = [&]( char const *p ) -> char const *
				{
					if( end - p < 8 )
						return nullptr;
					if( memcmp( p, "%PDF-", 5 ) != 0 )
						return p;
					if( !isdigit( p[5] ) || p[6] != '.' || !isdigit( p[7] ) )
						return p;
					return p + 8;
				};
				auto detectEnd = [&]( char const *p ) -> char const *
				{
					if( end - p < 5 )
						return nullptr;
					if( memcmp( p, "%%EOF", 5 ) != 0 )
						return p;
					return p + 5;
				};
				char const
					*scn = to_address( processRegion.begin() ),
					*next, *header;
				end = scn + processRegion.size();
				while( scn != end )
				{
					next = detectBegin( scn );
					if( !next )
						goto nextRegion;
					if( next == scn )
					{
						++scn;
						continue;
					}
					header = scn;
					for( scn = next; scn != end; ++scn )
					{
						next = detectEnd( scn );
						if( !next )
							goto nextRegion;
						if( next != scn )
						{
							savePdf( header, next - header );
							scn = next;
							break;
						}
					}
				}
			nextRegion:;
			}
	}
	catch( exception const &exc )
	{
		cout << exc.what() << endl;
	}
}

void savePdf( char const *header, size_t nBytes )
{
	string strFileName;
	for( unsigned iFileNo = 0; ; )
	{
		strFileName = (ostringstream() << iFileNo << ".pdf").str();
		using FIND_HANDLE = unique_ptr<void, decltype([]( HANDLE h ) { h && h 
!= INVALID_HANDLE_VALUE && FindClose( h ); })>;
		WIN32_FIND_DATAA fd;
		FIND_HANDLE fh( FindFirstFileA( strFileName.c_str(), &fd ) );
		if( fh.get() == INVALID_HANDLE_VALUE )
			if( DWORD dwErr = GetLastError(); dwErr == ERROR_FILE_NOT_FOUND )
				break;
			else
				throw system_error( (int)dwErr, system_category(), "error 
enumerating files to write" );
		if( !++iFileNo )
			return;
	}
	ofstream ofs;
	ofs.exceptions( ofstream::failbit | ofstream::badbit );
	ofs.open( strFileName.c_str(), ofstream::out | ofstream::trunc | 
ofstream::binary );
	ofs.write( header, nBytes );
}

template<typename Fn>
	requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) 
} -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn );

template<typename FilterFn>
	requires requires( FilterFn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( 
mbi ) } -> std::convertible_to<bool>; }
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess, 
FilterFn filterFn )
{
	vector<vector<MEMORY_BASIC_INFORMATION>> vvmbis;
	enumProcessMemory( hProcess, [&]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
		{
			if( !filterFn( mbi ) )
				return true;
			if( !vvmbis.size() || vvmbis.back().back().BaseAddress != 
mbi.BaseAddress )
				vvmbis.emplace_back( vector<MEMORY_BASIC_INFORMATION>() );
			vvmbis.back().emplace_back( mbi );
			return true;
		} );
	return vvmbis;
}

template<typename Fn>
	requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) 
} -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn )
{
	MEMORY_BASIC_INFORMATION mbi;
	for( char *last = nullptr; ; last = (char *)mbi.BaseAddress + 
mbi.RegionSize )
	{
		size_t nBytes = VirtualQueryEx( hProcess, last, &mbi, sizeof mbi );
		if( nBytes != sizeof mbi )
			if( DWORD dwErr = GetLastError(); dwErr == ERROR_INVALID_PARAMETER )
				break;
			else
				throw system_error( (int)dwErr, system_category(), "can't query 
process pages" );
		if( !fn( mbi ) )
			break;
	}
}

Mit verschiedenen PDF-Readern funktioniert das auch einwandfrei und
der Code speichert alle in dem Prozess-Adressraum gefundenen PDF ab
0.pdf durchnummeriert und überschreibt dabei keine exisitierenden
Dateien.
Dummerweise funktoniert das nicht mit Adobe Digital Editions bzw.
ich vermute, dass die das PDF verschlüsselt im RAM halten und on
the fly entschlüsseln.

Back to ger.ct | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Onleihe Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-21 07:36 +0200
  Re: Onleihe Lothar Kimmeringer <news201705@kimmeringer.de> - 2022-04-21 18:59 +0200
    Re: Onleihe Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-22 05:13 +0200
      Re: Onleihe "Wendelin Uez" <wuez@online.de> - 2022-04-24 13:03 +0200
        Re: Onleihe Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-24 17:24 +0200
          Re: Onleihe Dietz Proepper <dietz-usenet@rotfl.franken.de> - 2022-04-24 18:14 +0200
            Re: Onleihe Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-24 19:01 +0200
              Re: Onleihe "Wendelin Uez" <wuez@online.de> - 2022-04-25 15:43 +0200
                Re: Onleihe Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-26 05:02 +0200
  Re: Onleihe "Wendelin Uez" <wuez@online.de> - 2022-04-21 15:02 +0200
  Re: Onleihe Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-18 08:30 +0200
    Es wird noch verrückter ... Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-23 13:07 +0200
      Und noch einen oben drauf Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-27 10:11 +0200
        Re: Und noch einen oben drauf "Wendelin Uez" <wuez@online.de> - 2022-05-27 12:11 +0200
          Re: Und noch einen oben drauf Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-27 19:39 +0200

csiph-web