1

I am reading binary file cmd.exe into unsigned chars array. Total bytes read into bytes_read are 153. I converted it to base64 string and then decode this string back (code from 2nd answer base64 decode snippet in c++) into vector<'BYTE>. Here BYTE is unsigned char. decodedData.size() is also 153. But when I write this vector to file in binary mode to get my cmd.exe file again I get only 1 KB file. What thing I missed?

// Reading size of file
    FILE * file = fopen("cmd.exe", "r+");
    if (file == NULL) return 1;
    fseek(file, 0, SEEK_END);
    long int size = ftell(file);
    fclose(file);
// Reading data to array of unsigned chars
    file = fopen("cmd.exe", "r+");
    unsigned char * myData = (unsigned char *)malloc(size);
    int bytes_read = fread(myData, sizeof(unsigned char), size, file);
    fclose(file);

    std::string encodedData = base64_encode(&myData[0], bytes_read);
    std::vector<BYTE> decodedData = base64_decode(encodedData);

////write data to file
    ofstream outfile("cmd.exe", ios::out | ios::binary);
    outfile.write((const char *)decodedData.data(), decodedData.size());

Update: Thanks @chux for suggesting "r+" --> "rb+" Problem resolved.

13
  • 1
    1 kb may be the smallest possible non-empty file... have you looked at the file? Commented Jul 31, 2017 at 18:19
  • 2
    Why are you using fopen in c++ code? Commented Jul 31, 2017 at 18:20
  • 1
    If cmd.exe is binary, it should also be read in binary mode. Commented Jul 31, 2017 at 18:20
  • 3
    Even worse than using fopen and fread in C++, why are you using malloc in C++ code? Commented Jul 31, 2017 at 18:23
  • 2
    Suggest "r+" --> "rb+" Commented Jul 31, 2017 at 18:25

1 Answer 1

2

You marked this as C++.

This is one C++ approach using fstream to read a binary file. To simplify for this example, I created a somewhat bigger m_buff than needed. From the comments, it sounds like your fopen("cmd.exe", "r+") was in error, so I'm only providing a C++ binary read.

Method tReader() a) opens a file in binary mode, b) reads the data into m_buff, and c) captures gCount for display.

It also demonstrates one possible use of chrono to measure duration.

#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock  HRClk_t; 
typedef HRClk_t::time_point                 Time_t;  
typedef std::chrono::microseconds           US_t;    
using   namespace std::chrono_literals;  // suffixes 100ms, 2s, 30us

#include <iostream>
#include <fstream>
#include <cassert>

class T516_t
{
   enum BuffConstraints : uint32_t {
      Meg           = (1024 * 1024),
      END_BuffConstraints
   };

   char*   m_buff;
   int64_t m_gCount;

public:

   T516_t()
      : m_buff (nullptr)
      , m_gCount (0)
      {
         m_buff = new char[Meg];
      }

   ~T516_t() = default;

   int exec()
      {
         tReader();
         return(0);
      }

private: // methods

   void tReader()
      {
         std::string pfn = "/home/dmoen/.wine/drive_c/windows/system32/cmd.exe";
         // open file in binary mode
         std::ifstream sIn (pfn, std::ios_base::binary);

         if (!sIn.is_open()) {
            std::cerr << "UNREACHABLE:  unable to open sIn " << pfn
                      << " priviledges? media offline?";
            return;
         }

         Time_t start_us = HRClk_t::now();
         do
         {
            // perform read
            sIn.read (m_buff, Meg);
            // If the input sequence runs out of characters to extract (i.e., the
            // end-of-file is reached) before n characters have been successfully
            // read, buff contains all the characters read until that point, and
            // both eofbit and failbit flags are set

            m_gCount = sIn.gcount();

            if(sIn.eof()) { break; } // exit when no more data

            if(sIn.failbit ) {
               std::cerr << "sIn.faileBit() set" << std::endl;
            }

         }while(1);
         auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);

         sIn.close();

         std::cout << "\n  " << pfn
                   << "   " << m_gCount << " bytes"
                   << "   " << duration_us.count() << " us"
                   << std::endl;

      } // int64_t tReader()

}; // class T516_t

int main(int , char**)
{
   Time_t start_us = HRClk_t::now();

   int retVal = -1;
   {
      T516_t   t516;
      retVal = t516.exec();
   }
   auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);

   std::cout << "  FINI   " << duration_us.count() << " us" << std::endl;
   return(retVal);
}

One typical output on my system looks like:

/home/dmoen/.wine/drive_c/windows/system32/cmd.exe   722260 bytes  1180 us   
FINI   1417 us

Your results will vary.

Your ofstream use looks good (so did not replicate).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.