How inject shellcode loaded from file? - c++

I have a big problem that stuck me and today makes tree days trying solve. How i can load a shellcode from a binary file and inject correctly in a target process? When tested only with shellcode on own source code of program example this works fine.
Why this not works when the shellcode comes from a file? Someone already had this problem someday?
Here is the code tested (adapted from this to show a MessageBox) >
#include <windows.h>
#include <iostream>
#include <fstream>
#include <future>
using namespace std;
int main(int argc, char** argv) {
int process_id = atoi(argv[1]);
//MessageBox
//char xcode[] = "\x31\xc9\x64\x8b\x41\x30\x8b\x40\xc\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x1\xda\x8b\x52\x78\x1\xda\x8b\x72\x20\x1\xde\x31\xc9\x41\xad\x1\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x4\x72\x6f\x63\x41\x75\xeb\x81\x78\x8\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x1\xde\x66\x8b\xc\x4e\x49\x8b\x72\x1c\x1\xde\x8b\x14\x8e\x1\xda\x31\xc9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd2\x83\xc4\xc\x59\x50\x51\x66\xb9\x6c\x6c\x51\x68\x33\x32\x2e\x64\x68\x75\x73\x65\x72\x54\xff\xd0\x83\xc4\x10\x8b\x54\x24\x4\xb9\x6f\x78\x41\x0\x51\x68\x61\x67\x65\x42\x68\x4d\x65\x73\x73\x54\x50\xff\xd2\x83\xc4\x10\x68\x61\x62\x63\x64\x83\x6c\x24\x3\x64\x89\xe6\x31\xc9\x51\x56\x56\x51\xff\xd0";
vector<char> xcode;
ifstream infile;
infile.open("shellcode.bin", std::ios::in | std::ios::binary);
infile.seekg(0, std::ios::end);
size_t file_size_in_byte = infile.tellg();
xcode.resize(file_size_in_byte);
infile.seekg(0, std::ios::beg);
infile.read(&xcode[0], file_size_in_byte);
infile.close();
HANDLE process_handle;
DWORD pointer_after_allocated;
process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
if (process_handle == NULL)
{
puts("[-]Error while open the process\n");
}
else {
puts("[+] Process Opened sucessfully\n");
}
pointer_after_allocated = (DWORD)VirtualAllocEx(process_handle, NULL, sizeof(xcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pointer_after_allocated == NULL) {
puts("[-]Error while get the base address to write\n");
}
else {
printf("[+]Got the address to write 0x%x\n", pointer_after_allocated);
}
if (WriteProcessMemory(process_handle, (LPVOID)pointer_after_allocated, &xcode[0] /*(LPCVOID) shellcode*/, sizeof(xcode), 0)) {
puts("[+]Injected\n");
puts("[+]Running the shellcode as new thread !\n");
CreateRemoteThread(process_handle, NULL, 100, (LPTHREAD_START_ROUTINE)pointer_after_allocated, NULL, NULL, NULL);
}
else {
puts("Not Injected\n");
}
return 0;
}

It is because you are using sizeof(xcode). In first case it is a string constant with size known at compile time. In your case, the second one, the sizeof (xcode) returns 4 (or 8 depending on architecture). You should use file_size_in_byte instead. See this piece of code:
pointer_after_allocated = (DWORD)VirtualAllocEx(process_handle, NULL, sizeof(xcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
....
if (WriteProcessMemory(process_handle, (LPVOID)pointer_after_allocated, &xcode[0] /*(LPCVOID) shellcode*/, sizeof(xcode), 0))
The sizeof is meaningless in both, VirtualAllocEx and WriteProcessMemory. Consider replacing with the size of the file:
pointer_after_allocated = (DWORD)VirtualAllocEx(process_handle, NULL, file_size_in_byte, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
....
if (WriteProcessMemory(process_handle, (LPVOID)pointer_after_allocated, &xcode[0], file_size_in_byte, 0))
As commented by Botje:
update 1: You can pass xcode.data() and xcode.size() instead
update 2: The C++ escape symbols \x31, four symbols (bytes), is a C++ textual hex representation of a binary byte. Is something meant to be read/edited by human. The real .bin file should not be a textual file with C++ escape symbols and can be edited with a hex editor.

Related

Why do I get special characters when getting the source code of a website? c++

I am trying to get the source code of Barack Obama's Wikipedia page and save it to a file.
Everything works well until I open the file and see some weird characters in it:
As you can see, EOT1024 appears in the file, but it does not appear in the website's actual source code, which I checked using Google Chrome. I would like to know why this is happening, and how I can stop it from happening.
My code:
#include <iostream>
#include <windows.h>
#include <wininet.h>
#include <fstream>
int main(){
std::string textLink = "https://en.wikipedia.org/wiki/Barack_Obama";
std::ofstream file;
HINTERNET hInternet, hFile;
char buf[1024];
DWORD bytes_read;
int finished = 0;
bool e=false;
std::string waste;
file.open("data.txt",std::ios::out);
hInternet = InternetOpenW(L"Whatever", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternet == NULL) {
printf("InternetOpen failed\n");
}
hFile = InternetOpenUrl(hInternet, textLink.c_str(), NULL, 0L, 0, 0);
if (hFile == NULL) {
printf("InternetOpenUrl failed\n");
}
while (!finished) {
if (InternetReadFile(hFile, buf, sizeof(buf), &bytes_read)) {
if (bytes_read > 0) {
file << bytes_read << buf;
}
else {
finished = 1;
}
}
else {
printf("InternetReadFile failed\n");
finished = 1;
}
}
InternetCloseHandle(hInternet);
InternetCloseHandle(hFile);
file.close();
}
I have the text file as I view it in Notepad++ right here:
https://drive.google.com/open?id=1Ty-a1o29RWSQiO1zTLym6XH4dJvUjpTO
I don't understand why I would get those characters in the data.txt file that I write to.
NOTE: occasionally, instead of seeing EOT1024, I even get EOT21, EOT1016, and other seemingly random characters.
You're literally writing the integer bytes_read to the file:
file << bytes_read << buf;
There's your "1024" (on the occasions that 1024 bytes were read).
Don't do that.
Furthermore, it looks like you're assuming buf is null-terminated. Instead, stream the first bytes_read of buf; that's why you have that integer.
So:
file.write(&buf[0], bytes_read);
Consult the documentation:
A normal read retrieves the specified dwNumberOfBytesToRead for each call to InternetReadFile until the end of the file is reached. To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.

Stackbased buffer overrun

When running my code I get the following error:
Unhandled exception at 0x00BA16A0 in GameLauncher.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
I have no idea what could be causing this. It is caused with the following code:
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
int main()
{
std::cout << "Which process would you like to close? (Include .exe)" << std::endl;
wchar_t userProcessToFind;
std::wcin.getline(&userProcessToFind, 20);
HANDLE processSnapshot;
DWORD processID = 0;
PROCESSENTRY32 processEntery;
processEntery.dwSize = sizeof(PROCESSENTRY32);
processSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, processID);
if(Process32First(processSnapshot, &processEntery) == TRUE)
{
while (Process32Next(processSnapshot, &processEntery) == TRUE)
{
if (_wcsicmp(processEntery.szExeFile, &userProcessToFind) == 0)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, processEntery.th32ProcessID);
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}
CloseHandle(processSnapshot);
}
return 0;
}
In
wchar_t userProcessToFind;
std::wcin.getline(&userProcessToFind, 20);
You have allocated space for a single wchar_t but you are trying to read in up to 20 characters and place it in the memory at the address of userProcessToFind. This will cause stack corruption as you are going to try to write into memory that does not belong to &userProcessToFind. What you need to do is create an array like
wchar_t userProcessToFind[20];
std::wcin.getline(userProcessToFind, 20);
Or you could use a std::wstring and your code would become
std::wstring userProcessToFind;
std::getline(std::wcin, userProcessToFind);
This gives the benefit of not having to use an arbitrary size for the process name as std::wstring will scale to fit the input. If you need to pass the underlying wchar_t* to a function you can use std::wstring::c_str() to get it.

Dll injection with GetFullPathNameA not working?

If I explicitly write the address the dll injection works
char s[1000]="E:\\worldisnotenough.dll"; //Works
If I use GetFullPathNameA DLL injections do not work, and they do not give any runtime or compile time errors. I checked this:
char s[1000];
int ax =GetFullPathNameA("worldisnotenough.dll",
1000,
s, //Output to save the full DLL path
NULL);
std::cout<<s; //prints the correct path. Working.
The line cout << s prints the correct path, but DLL injection doesn't happen. No errors occur. I checked VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread, and all of them are working properly.
Edit: complete code
#include <QCoreApplication>
#include<windows.h>
#include<tchar.h>
#include<iostream>
#include "E:/Users/Gen/qt project freiza/FreizaLibrary/freizalibrary.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// FreizaLibrary lib;
// QTextStream s(stdin);
// QString value = s.readLine();
// lib.injection(value.toInt());
int procID = 13044;
HANDLE hHandle = OpenProcess( PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ,
FALSE,
procID );
QString dllName = "worldisnotenough.dll";
QFile myDllFile(dllName);
QFileInfo dllInfo(dllName);
QString str =dllInfo.absoluteFilePath();
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll";
std::cout<<strlen(s)<<"\n";
int ax =GetFullPathNameA("worldisnotenough.dll",
86, //I set it to 1000 before posting this question.
s, //Output to save the full DLL path
NULL);
//qDebug()<< QString::fromUtf8(s) <<" "<< ax;
std::cout<<s<<"size "<<ax;
LPVOID dllPathAddr = VirtualAllocEx(hHandle,
0,
strlen(s),
MEM_RESERVE|MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
std::cout<<" test \n";
std::cout<<(int*)dllPathAddr<<endl;
if(dllPathAddr==NULL)
{
qDebug()<<"virtual failed";
}
size_t x;
int n= WriteProcessMemory(hHandle,
dllPathAddr,
s,
strlen(s),
&x);
if(n==0)
{
qDebug()<<"write failed";
}
std::cout<<endl<<n<<"\t"<<x;
LPVOID addr = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
if(addr==NULL)
{
qDebug()<<"get proc failed";
}
HANDLE rThread = CreateRemoteThread(hHandle, NULL, 0, (LPTHREAD_START_ROUTINE)addr,dllPathAddr, 0, NULL);
if(rThread==NULL)
{
qDebug()<<"create remote failed";
}
WaitForSingleObject(rThread, INFINITE);
VirtualFreeEx(hHandle, dllPathAddr, 0, MEM_RELEASE);
CloseHandle(hHandle);
qDebug()<< "done";
return a.exec();
}
And why negative votes?
When I post full code. People say only post the segment of code which is not working.
And I explained the situation to its fullest. Because of these negative votes now I won't be able to ask questions on stackoverflow. Thank you.
Your problem is you are trying to use a statically defined character array as a buffer for GetFullPathNameA!
See here:
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll";
std::cout<<strlen(s)<<"\n";
int ax =GetFullPathNameA("worldisnotenough.dll",
86, //1000 is no good, MAX_PATH is 260
s, //Using 's' as a buffer? Don't do that please!
NULL);
Furthermore when using the ANSI version which you are as denoted by the 'A' a maximum path length of 260 characters is the maximum. MAX_PATH==260
"In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" "
Fixed code: (However I don't use QT so that is missing from here, shouldn't matter though as it wasn't used for anything needed for the injecting to work)
#include <windows.h>
#include <iostream>
#include <tlhelp32.h>
HANDLE GetProcessHandle(wchar_t *ProcessName,ULONG *ReturnedProcessId);
int main(int argc, char *argv[])
{
ULONG procID;
HANDLE hHandle=GetProcessHandle(L"ExeToInjectInto.exe",&procID);
/*HANDLE hHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,procID);*/
std::cout<<"handle: "<<hHandle<<" process ID: "<<procID<<"\n";
char s[]="C:\\Users\\DBVM_OS\\CodeBlocksProjects\\HelpFreizaProject\\bin\\Debug\\mytestdll.dll";
std::cout<<s<<"\n"<<strlen(s)<<"\n";
//First Problem:
/*In the ANSI version of this function, the name is limited to MAX_PATH characters.
To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\"
*/
//Second Problem:
/* Don't use a defined static char[] as a buffer! allocate some memory or use the stack */
//char s2[MAX_PATH];
//int ax=GetFullPathNameA("mytestdll.dll",MAX_PATH,s2,0);
char *s2=new char[MAX_PATH];
if(s2==0) return 0;
int ax=GetFullPathNameA("mytestdll.dll",MAX_PATH,s2,0);
std::cout<<s2<<"\nsize returned: "<<ax<<" strlen: "<<strlen(s2)<<"\n";
LPVOID dllPathAddr=VirtualAllocEx(hHandle,0,(strlen(s2)+1),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
std::cout<<"Remotely Allocated String Address: \n";
std::cout<<(int*)dllPathAddr<<"\n";
if(dllPathAddr==0)
{
OutputDebugStringA("VirtualAllocEx failed...");
return 0;
}
SIZE_T x;
BOOL n=WriteProcessMemory(hHandle,dllPathAddr,s2,(strlen(s2)+1),&x);
if(n==FALSE)
{
OutputDebugStringA("write failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
std::cout<<"WriteProcessMemory Success: "<<n<<", Bytes Written: "<<x<<"\n";
LPVOID addr=(LPVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryA");
if(addr==0)
{
OutputDebugStringA("get proc failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
std::cout<<"LoadLibraryA: "<<addr<<"\n";
HANDLE rThread=CreateRemoteThread(hHandle,0,0,(LPTHREAD_START_ROUTINE)addr,dllPathAddr,0,0);
if(rThread==0)
{
OutputDebugStringA("create remote failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
WaitForSingleObject(rThread,INFINITE);
std::cout<<"DLL Should have been injected successfully at this point...\nFreeing remote string";
BOOL freed=VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
if(freed==0) OutputDebugStringA("Freeing Remote String Failed...");
delete[] s2; //if you dynamically allocated s2 like I've done...
CloseHandle(hHandle);
return 0;
}
HANDLE GetProcessHandle(wchar_t *ProcessName,ULONG *ReturnedProcessId)
{
PROCESSENTRY32W pe;
HANDLE Snap;
ZeroMemory(&pe, sizeof(PROCESSENTRY32W));
pe.dwSize=sizeof(PROCESSENTRY32W);
Snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(Snap==INVALID_HANDLE_VALUE) return 0;
BOOL bProcess=Process32FirstW(Snap,&pe);
while(bProcess)
{
if(_wcsicmp(pe.szExeFile,ProcessName)==0)
{
HANDLE ProcessHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,pe.th32ProcessID);
if(ReturnedProcessId!=0)
*ReturnedProcessId=pe.th32ProcessID;
CloseHandle(Snap);
return ProcessHandle;
}
bProcess=Process32NextW(Snap, &pe);
}
if(ReturnedProcessId!=0) *ReturnedProcessId=0;
CloseHandle(Snap);
return 0;
}
you need to use
strlen(s)+1
cause it returnes the lenght of the string without including the terminating null character itself! So VirtualAllocEx and WriteProcessMemory will not write the '\0' char and the filename will terminate at a "random" position in memory.
Also
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll"; //- Length: 93+1
int ax =GetFullPathNameA("worldisnotenough.dll",
sizeof(s), //<-- old: 86 but s[] is 93 + 1 if this has to hold the total path may it was to small?
s, //Output to save the full DLL path
NULL);
looks wong?!

Why Am I Writing 0 bytes with WriteFile?

I'm trying to make a program that finds the next .exe file in a user-defined directory and writes a flag to it (for a computer security class).
It's currently writing 0 bytes, and I'm not sure why.
Here is my code so far:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <fstream>
using namespace std;
typedef wchar_t wchar;
struct thePlague{
long int origBytes;
wchar_t flag[6];
};
void main() {
WIN32_FIND_DATA findFileData; //Windows structure that receives info about a found file or directory
HANDLE hFind = INVALID_HANDLE_VALUE; //Handle that holds whether or not a file was successfully found with FindNextFile
LARGE_INTEGER fileSize;
wchar szDir[MAX_PATH];
DWORD dwError = 0;
wchar directory[MAX_PATH];
wcout<<L"Please enter a directory: ";
wcin>>directory;
// Check that the input path plus 7 is not longer than MAX_PATH.
// 7 characters are for the "\*.exe" plus NULL appended below.
if (wcslen(directory) > (MAX_PATH - 7)) {
wcout<<L"\nDirectory is too long\n";
return;
}
wcout<<L"Target directory is: "<<directory<<endl;
// Prepare string for use with FindFile functions. First, copy the
// string to a buffer, then append '\*' to the directory name.
wcscpy(szDir, directory);
wcscat(szDir, L"\\*.exe");
//Find the first file in the directory
hFind = FindFirstFile(szDir, &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
wcout<<L"FindFirstFile Failed"<<GetLastError()<<endl;
return;
}
do {
fileSize.LowPart = findFileData.nFileSizeLow;
fileSize.HighPart = findFileData.nFileSizeHigh;
wcout<<findFileData.cFileName<<L" "<<fileSize.QuadPart<<L" bytes\n";
DWORD dwBytesWritten = 0; //# of bytes written by WriteFile
wchar_t *buffer = (wchar *)malloc(sizeof(thePlague)); //A buffer the size of our struct (infection flag)
wofstream writeToBuffer(buffer, ios::binary); //Open the buffer for writing
thePlague newVictim; //New infection flag
writeToBuffer.write((const wchar_t*)&newVictim, sizeof(thePlague));
writeToBuffer.close();
DWORD dwErrorFlag;
dwErrorFlag = WriteFile(hFind, //The handle holding the file we are writing to
buffer, //The buffer holding what we want to write to the file, in this case a struct
sizeof(thePlague), //How many bytes to write to the file
&dwBytesWritten, //Where to store the # of bytes successfully written
NULL //Where to write to incase of overlap
);
if (dwErrorFlag == false)
wcout<<L"Error was: "<<GetLastError()<<endl;
wcout<<L"# of bytes written: "<<dwBytesWritten<<endl;
} while(FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
return;
}
When I run this, I get:
Please enter a directory: C:\Infect
Target directory is: C:\Infect
hello.exe 65536 bytes
Error was: 6
# of bytes written: 0
Press any key to continue . . .
I know this is an ERROR_INVALID_HANDLE, but how do I fix this?
You need to open the file before writing to it. Your HANDLE hFind is just a handle to iterate over directories/files, not an open handle to a file.
Use CreateFile() to open the file
FindFirstFile returns a search handle, but WriteFile requires an open file handle. Use CreateFile to open the file before writing to it with WriteFile.

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.