How to read pkcs#7 file properly - c++

I have a file with detached pkcs#7 signature of size 267 bytes. I create it after executing
CryptSignMessage(
&SigParams,
TRUE,
1,
MessageArray,
MessageSizeArray,
pbSignedMessageBlob,
&cbSignedMessageBlob)
function and then I write content of pbSignedMessageBlob:
pbSignedMessageBlob[cbSignedMessageBlob] = '\0';
FILE *file;
file = fopen("c:\\path\\sign_pkcs7.pk7", "wb");
fwrite(pbSignedMessageBlob, sizeof(BYTE), cbSignedMessageBlob, file);
fclose(file);
Then I try to verify this signature and read this file:
BYTE *pkcsContent;
FILE *file3;
file3 = fopen("c:\\users\\timur\\desktop\\sign_pkcs7.pk7", "rb");
pkcsContent = MyReadFile(file3, cbArray);
BYTE* MyReadFile(FILE *f, DWORD &len)
{
size_t result;
BYTE *buffer;
if (f == NULL)
{
fputs ("File error", stderr);
exit (1);
}
fseek (f, 0, SEEK_END);
len = ftell (f);
rewind (f);
//buffer = (BYTE*) malloc (sizeof(char)*lSize);
buffer = new BYTE[len + 1];
if (buffer == NULL)
{
fputs ("Memory error", stderr);
exit (2);
}
result = fread (buffer, 1, len, f);
if (result != len)
{
fputs ("Reading error",stderr);
exit (3);
}
buffer[len] = '\0';
fclose (f);
return buffer;
}
But the file content I get into pkcsContent is only 37 bytes length.
I also tried to manage files using std::fstream, but result is the same. Maybe the way I'm writing file to disk is wrong?

Are you trying to compute the length of pkcsContent with strlen (this is my guess since you're null-terminating the buffer in MyReadFil)? You can't do that because PKCS#7 is binary data and it can contain 0 anywhere.

Related

C++: fopen() returns handle to empty file

I'm getting a strange file handle from fopen; the pointer itself isn't NULL, but the file it represents has no size, and feof(file) is already set... what could be causing this?
(I triple checked the file itself, it exists, has data, and the file's permissions are okay... and filename is set to "source/test_file.object.txt")
bool tagFile(const char * filename){
FILE * file = fopen(filename, "r");
if(file == NULL){ // file is not NULL
printf(" Couldn't open the file %s", filename);
return false;
}
int size = fseek(file, 0, SEEK_END); // size is 0
rewind(file);
while(feof(file)){
.... // never executes because feof(file) fails
}
}
0x002cc410 // value of 'file' in the debugger
_ptr=0x00000000 <Bad Ptr>
_cnt=0
_base=0x00000000 <Bad Ptr>
_flag = 1
_file = 3
The most common cause of this is simply opening a file which is empty. There are no bytes to read so EOF is immediate, but the file exists so fopen can't return NULL.

_read function is returning obsolete values for file handle

The block of code here runs fine till the _read function is called, after that it changes the value of file handle variable 'fh' for no reason.
std::string& xLogFile;
std::string& xBuffer;
struct _stat& xStatBuffer)
char *buffer;
buffer = (char *)malloc(sizeof(char) * xStatBuffer.st_size);
#define _O_RDONLY 0x0000 /* open for reading only */
int fh = 0, read_bytes =0;
fh = _open(xLogFile.c_str(), _O_RDONLY); // ToDo function deprecated should be changed to fstream
if (fh ==1)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't open the log file");
return true;
}
read_bytes = _read(fh,&buffer,xStatBuffer.st_size);
_close(fh);
if (read_bytes <= 0)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't read the log file");
return true;
}
buffer[read_bytes] = '\0';
xBuffer = buffer;
This is a block of code i am using to read from a file into a buffer, but it is failing at the _read function, where the value of file handle 'fh' changes after the call to the function.
Fix the code as below, buffer and not &buffer. You are overwriting the stack.
read_bytes = _read(fh,buffer,xStatBuffer.st_size);

Wrong value of UID in stat() and wrong pr_pid in psinfo_t

My function reads process list from /proc, then read process psinfo file into proper sturcture, as well as data about this file, and prints it.
The problem is, some of the data in those structures is wrong. As usual, the moment when program partially works, is the most confusing. It reads all data correct, except for PID (pr_pid), which is always 0, and UID of a file, which is also always 0. Why? Is it possible for data to load partially correctly? That shouldn't be possible.. 0 would be possible if we were talking about PPID, but solaris documentation clearly states pr_pid is the PID.
Links which I thought would have answers, but I couldn't find one:
http://docs.oracle.com/cd/E19963-01/html/821-1473/proc-4.html
http://linux.die.net/man/3/getpwnam
http://linux.die.net/man/2/stat
code:
void printProcessInformation(char pid[]){
//find full path name to your "stat" file
//DIR *dir;
//struct dirent *ent;
//Creating string with /proc/PID
char * s = malloc(snprintf(NULL, 0, "%s%s", "/proc/", pid) + 1);
sprintf(s, "%s%s", "/proc/", pid);
//Creating string with /proc/PID/psinfo (full path)
char * fullPath = malloc(snprintf(NULL, 0, "%s%s", s, "/psinfo") + 1);
sprintf(fullPath, "%s%s", s, "/psinfo");
free(s);
//printf("%s\n",fullPath);
//Reading data from file
FILE* file = fopen(fullPath, "r");
char* buffer;
buffer = (char*) malloc(sizeof(psinfo_t));
if(file == NULL)
{
perror("Error: Couldn't open file");
return;
}
fread((void *)buffer, sizeof(psinfo_t), 1, file);
psinfo_t* pData = (psinfo_t*) buffer;
free(buffer);
buffer = (char*) malloc(sizeof(stat));
stat(file,buffer);
struct stat* fileStat=(struct stat*) buffer;
printf("File owner id:%d\n",fileStat->st_uid);
free(buffer);
fclose(file);
struct passwd* pw=getpwuid(fileStat->st_uid);
//Loading data from structures
time_t sTime=pData->pr_start.tv_sec;
int pr_pid=pData->pr_pid;
char* fname=pData->pr_fname;
char* uid=pw->pw_name;
printf("%8s %5d %16s %.24s\n", uid, pr_pid, fname, ctime(&sTime));
}
Look at this:
psinfo_t* pData = (psinfo_t*) buffer;
free(buffer);
...
int pr_pid=pData->pr_pid;
You're setting pData to the contents of buffer in the first line and then freeing it. What pData points to is now lost to you, it may in fact be reused in the next malloc. When you try to use it in the last line above you're reading who knows what. You're freeing too agressively in this case. Don't free pData, (indirectly through buffer) until you're done using it.

C++ fwrite doesn't write to text file, have no idea why?

I have this code that basically reads from file and creates new file and write the content from the source to the destination file. It reads the buffer and creates the file, but fwrite
doesn't write the content to the newly created file, I have no idea why.
here is the code. (I have to use only this with _sopen, its part of legacy code)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
FILE* pfFile;
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
pfFile = fdopen(iFileId, "r");
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
// buffer = (char*) malloc (sizeof(char)*lSize);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
return false;
}
// copy the file into the buffer:
result = fread (buffer,lSize,1,pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
return 0;
}
You can make main file and try it see if its working for you .
Thanks
Change your code to the following and then report your results:
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
{
FILE* pfFile;
if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
{
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
if ((buffer = (char*) malloc (lSize)) == NULL)
return false;
// copy the file into the buffer:
result = fread (buffer,(size_t)lSize,1,pfFile);
fclose(pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
{
if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
{
size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
printf ("elements written <%d>\n", f);
if (f == 0)
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
}
}
}
}
return 0;
}
[edit]
for other posters, to show the usage/results of fwrite - what is the output of the following?
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = fopen ("f.kdt", "w+");
printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));
fclose (fp);
}
[/edit]
sizeof(buffer) is the size of the pointer, i.e. 4 and not the number of items in the buffer
If buffer is an array then sizeof(buffer) would potentially work as it returns the number of bytes in the array.
The third parameter to fwrite is sizeof(buffer) which is 4 bytes (a pointer). You need to pass in the number of bytes to write instead (lSize).
Update: It also looks like you're missing the flag indicating the file should be Read/Write: _O_RDWR
This is working for me...
std::string szdes = "C:\\temp\\test_des.txt";
FILE* pDesfFile;
int iFileId2;
err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, lSize, pDesfFile );
fclose (pDesfFile);
Since I can't find info about _sopen, I can only look at man open. It reports:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Your call _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE); doesn't match either one of those, you seem to have flags and 'something' and modes / what is SH_DENY?
What is the result of man _sopen?
Finally, shouldn't you close the file descriptor from _sopen after you fclose the file pointer?
Your final lines should look like this, btw :
if (iFileId2 >= 0)
{
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
fclose (pDesfFile);
}
Since you currently write the file regardless of whether or not the fdopen after the O_CREAT succeeded. You also do the same thing at the top, you process the read (and the write) regardless of the success of the fdopen of the RDONLY file :(
You are using a mixture of C and C++. That is confusing.
The sizeof operator does not do what you expect it to do.
Looks like #PJL and #jschroedl found the real problem, but also in general:
Documentation for fwrite states:
fwrite returns the number of full items actually written, which may be less than count if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
So if the return value is less than the count passed, use ferror to find out what happened.
The ferror routine (implemented both as a function and as a macro) tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.

How do I extract a user stream from a WinDbg extension?

I have embedded a custom stream in a dump (i.e. passed the UserStreamParam argument to MiniDumpWriteDump function). Now, I'm trying to extract the stream from a WinDbg extension. (Note that I have verified that I can retrieve the stream using the MiniDumpReadDumpStream function).
I'm using the IDebugAdvanced2::Request method with DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM request. I am able to retrieve data from standard streams. For example, the following snippet will correctly retrieve the contents of the misc info stream.
DEBUG_READ_USER_MINIDUMP_STREAM rums = {};
rums.StreamType = MiscInfoStream;
rums.Buffer = &buf;
rums.BufferSize = sizeof buf;
hr = p->Request(DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM,
&rums, sizeof rums, 0, 0, 0);
However, trying to retrieve my own stream will result in an error (0x80070570, ERROR_FILE_CORRUPT) and WinDbg outputs
Dir entry 11, ??? stream has unknown stream type 6381921
Note that the same message appears as a part of the .dumpdebug output.
Stream 11: type ??? (6381921), size 00000038, RVA 00033FA9
Dir entry 11, ??? stream has unknown stream type 6381921
What is the problem? How do I retrieve contents of my user stream?
very late answer
StreamType cannot be UserDefined StreamTypes
jen-lung chiu of ms posted so in osronline windbg lists long back
do not know if the latest dbgeng has this limitation eliminated
you either retrieve it with a dbghelp function independently
(using dbghelp functions inside windbg extensions are not recommended )
or parse the stream yourself with fopen() fread() like below
userstream:\>type ..\usrstr.cpp
#include <stdio.h>
#include <engextcpp.hpp>
#include <dbghelp.h>
const ULONG MBUFFSIZE = 0x1000;
PVOID Buff = 0;
int __cdecl ReadUserStream (char *dmpfile)
{
PMINIDUMP_HEADER MiniHeader = 0;
PMINIDUMP_DIRECTORY MiniDir = 0;
PMINIDUMP_USER_STREAM userstream = 0;
size_t result = 0;
ULONG Streams =0;
ULONG i = 0;
FILE * fp = fopen(dmpfile,"rb");
if (fp)
{
result = fread(Buff, 1, sizeof(MINIDUMP_HEADER), fp );
if ( result == sizeof(MINIDUMP_HEADER) )
{
MiniHeader = (PMINIDUMP_HEADER) Buff;
Streams = MiniHeader->NumberOfStreams;
for (i = 0; i < Streams; i++ )
{
result = fread( Buff, 1, sizeof(MINIDUMP_DIRECTORY), fp );
if ( result == sizeof(MINIDUMP_DIRECTORY) )
{
MiniDir = (PMINIDUMP_DIRECTORY) Buff;
if ( MiniDir->StreamType > LastReservedStream )
{
userstream = (PMINIDUMP_USER_STREAM)Buff;
ULONG savedbuffsize = userstream->BufferSize;
ULONG savedtype = userstream->Type;
PCHAR savedbufferptr = (PCHAR)userstream->Buffer;
long pos = ftell(fp);
fseek(fp, (long)savedbufferptr,SEEK_SET);
result = fread( Buff, 1, savedbuffsize, fp );
if ( result == savedbuffsize )
{
printf(
"\n"
"Datastream Type = %.8x\n"
"Buffer Size = %.8x\n"
"Buffer = %p\n"
"Buffer content = %s\n"
"\n",
savedtype,
savedbuffsize,
savedbufferptr,
Buff
);
fseek(fp,pos,SEEK_SET);
continue;
}
else
{
printf(
"failed to read buffer contents at offset %p of
user stream %x\n",
savedbufferptr,
savedtype);
fseek(fp,pos,SEEK_SET);
continue;
}
}
}
else
{
printf("failed to fread Minidump directory exiting \n");
goto getout;
}
}
}
else
{
printf("failed to fread Minidump header exiting \n");
goto getout;
}
}
else
{
printf("failed to open dmp file exiting \n");
goto getout;
}
getout:
if (fp)
fclose(fp);
return 0;
}
int __cdecl main (int argc, char * argv[])
{
if (argc !=2)
{
printf("Usage %s %s\n",argv[0],"somedump.dmp");
return 0;
}
Buff = malloc( MBUFFSIZE );
if (Buff)
{
ReadUserStream(argv[1]);
free(Buff);
return 0;
}
else
{
printf("malloc failed exiting\n");
return 0;
}
}
output from an userdump that has userStreams in it
(oleg staradumov debuginfo.com writeuserstream.cpp )
userstream:\>usrstr.exe
Usage usrstr.exe somedump.dmp
userstream:\>usrstr.exe test.dmp
Datastream Type = 00010000
Buffer Size = 00000021
Buffer = 000010B6
Buffer content = This is the first data stream...
Datastream Type = 00010001
Buffer Size = 00000023
Buffer = 000010D7
Buffer content = and this is the second data stream
I found this topic while looking for a method to read out user stream from the dbg file.
#blabb 's answer is correct in basics and helped me a lot, but it has a two flaws:
You should use the MINIDUMP_HEADER.StreamDirectoryRva to locate the MINIDUMP_DIRECTORY list.
You should not convert the MINIDUMP_DIRECTORY entry to MINIDUMP_USER_STREAM, because that's an error (MINIDUMP_USER_STREAM is a bigger struct than MINIDUMP_DIRECTORY, so you are reading uninitialized memory there) Use the MINIDUMP_DIRECTORY to locate the needed part of the stream.
Even if not tested, it should work if you fill StreamType with a custom value (greater than LastReservedStream = 0xFFFF) instead of MiscInfoStream.