Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > [C++ WinAPI]Скопировать содержимое exe файла


Автор: Bugmaker 5.4.2009, 18:14
Как программно прочитать содержимое exe файла? Допустим виндового calc.exe.
Пробовал fopen\fgets.. не получается.

Может я вообще не тем путем иду? хочу программно создать exe файл без копирования.
То есть допустим запускаю программу на другом компе а она там создает exe файл с нужным содержимым.
Можно ли это реализовать, и будет ли вообще такой файл потом корректно запускаться?

Автор: GremlinProg 5.4.2009, 18:19
Перемещено в "С/C++ общие вопросы"

Автор: andrew_121 5.4.2009, 18:51
Bugmaker, Да, можно. Но на стадии компиляции тебе нужно содержимое файла преобразовать в массив значений, и при запуске проги его записывать в файл.

Автор: GoldFinch 5.4.2009, 18:58
в ресурсы его засунь

Автор: xvr 5.4.2009, 20:08
Цитата(Bugmaker @ 5.4.2009,  18:14)
Как программно прочитать содержимое exe файла? Допустим виндового calc.exe.
Пробовал fopen\fgets.. не получается.

fopen можно (только не забыть поставить ему бинарную моду чтения 'rb'). fgets - нельзя. Он читает строки, разделенные символом конца строки ('\n'), в бинарнике они могут быть где угодно. Пользуй fread
Цитата

То есть допустим запускаю программу на другом компе а она там создает exe файл с нужным содержимым.
Запросто - вирусы же создают  smile 
Цитата

Можно ли это реализовать, и будет ли вообще такой файл потом корректно запускаться?
И запускают, и создают, и запускают, и созда...  smile 
Повбивав бы  smile 

Автор: GoldFinch 5.4.2009, 20:11
xvr, такое поведение еще свойственно инсталляторам

Автор: Bugmaker 6.4.2009, 00:05
Не могу нагуглить ниодного простого примера... толи спать уже пора.

Код

#include "windows.h"
#include <iostream>

 
using namespace std;
int main()
{
    FILE *file;
    char *buffer;
    
file = fopen( "calc.exe", "rb" );
if( file != 0 )
{
fread( buffer, 1,20, file); 
cout << buffer << endl;
}
else
{
cout << "File not found !!!" << endl;
}
fclose(file);
system ("PAUSE");
}



Вот такой код выводит кусок файла.
Скажите, что где поменять чтобы прочесть весь файл.

fread( buffer, 1,20, file);  если пытаюсь менять цифры 1 и 20 на другие то программа иногда вообще закрывается сразу после запуска сама.

Вобщем ссылочку бы на подробное описание или пример было бы неплохо.

Спасибо всем, кто откликнулся.

Автор: zim22 6.4.2009, 07:15
Цитата(Bugmaker @  6.4.2009,  00:05 Найти цитируемый пост)
Вобщем ссылочку бы на подробное описание или пример было бы неплохо.

http://www.cplusplus.com/reference/clibrary/cstdio/fread.html
http://msdn.microsoft.com/ru-ru/library/kt0etdcs.aspx

Автор: GoldFinch 6.4.2009, 08:23
программа ведь под винду пишется? зачем тогда юзать fopen и т.п.
вроде бы надо "программно создать exe файл" зачем тогда его считывать? надо же написать программу которая пишет файл
а та которая считывает  - это совсем другой код

можно конечно написать программу которая при запуске с параметром "имя файла" записывает в себя этот файл, а при запуске без параметра записывает этот файл на диск, но разве это надо?

Автор: xvr 6.4.2009, 10:27
Цитата(Bugmaker @ 6.4.2009,  00:05)
Не могу нагуглить ниодного простого примера... толи спать уже пора.

Код

#include "windows.h"
#include <iostream>

 
using namespace std;
int main()
{
    FILE *file;
    char *buffer;
    
file = fopen( "calc.exe", "rb" );
if( file != 0 )
{
fread( buffer, 1,20, file); 
cout << buffer << endl;
}
else
{
cout << "File not found !!!" << endl;
}
fclose(file);
system ("PAUSE");
}



Вот такой код выводит кусок файла.
Скажите, что где поменять чтобы прочесть весь файл.

fread( buffer, 1,20, file);  если пытаюсь менять цифры 1 и 20 на другие то программа иногда вообще закрывается сразу после запуска сама.

Вобщем ссылочку бы на подробное описание или пример было бы неплохо.

Спасибо всем, кто откликнулся.

buffer должен быть описан как char buffer[20]; Выводить его в cout через << не получится - это бинарные данные, что там выведется неизвестно

Автор: Bugmaker 6.4.2009, 18:10
GoldFinch  ты прав, нужно создать exe.  Но если я просто открою calc.exe в блокноте, все скопирую и через fputs помещу в exe файл, он же не будет работать не так ли?

xvr как корректно вывести бинарные данные? 


Автор: GoldFinch 6.4.2009, 18:47
Bugmaker, для копирования файла в большинстве случаев подойдет 
copy dropper.exe+calc.exe dropper.exe

затем dropper.exe должен будет записать calc.exe из конца себя на диск

Автор: JAnty 6.4.2009, 18:50
Есть такой язык не С++, а С.
 fprintf и fscanf читая и записывая символы как числа или наоборот. 

Не забывайте, что С могучей чем С++!!!

Автор: GoldFinch 6.4.2009, 18:54
JAnty, там понял что написал?

Автор: JAnty 6.4.2009, 18:58
GoldFinch да, я это уже делал. Я делал ехе файлы через принтф.

Автор: zim22 6.4.2009, 20:03
Цитата(JAnty @  6.4.2009,  18:58 Найти цитируемый пост)
GoldFinch да, я это уже делал. Я делал ехе файлы через принтф.

приведите пример. дабы не быть голословным.

Автор: xvr 6.4.2009, 20:24
Цитата(Bugmaker @ 6.4.2009,  18:10)
xvr как корректно вывести бинарные данные?

Вывести куда? Если в stdout - то никак. Это текстовый поток и он не рассчитан на вывод бинарных данных. (Точнее, если перенаправить вывод из программы в файл, то в такой stdout вывести можно, но это уже за рамками)
Для копирования из файла в файл можно использовать fread/fwrite. Для создания файла из ресурсов - FindResource/LoadResource/LockResource + fwrite
Для помещения файла в ресурс нужно добавить в проект *.rc файл такого содержания
Код

CFG_dgrs_cfg     RCDATA  DISCARDABLE     "dgrs.cfg"
CFG_trs_cfg      RCDATA  DISCARDABLE     "trs.cfg"
Первый столбец - идентификатор ресурса (по нем FindResource будет искать),  последний - имя исходного файла

Добавлено через 1 минуту и 38 секунд
Цитата(zim22 @ 6.4.2009,  20:03)
Цитата(JAnty @  6.4.2009,  18:58 Найти цитируемый пост)
GoldFinch да, я это уже делал. Я делал ехе файлы через принтф.

приведите пример. дабы не быть голословным.

Это сделать можно (через printf("%c",byte);) Но с тем же успехом можно и гланды через жо... удалять  smile 

Автор: zim22 6.4.2009, 20:33
Цитата(xvr @  6.4.2009,  20:24 Найти цитируемый пост)
Это сделать можно (через printf("%c",byte);) Но с тем же успехом можно и гланды через жо... удалять

интересно дождаться варианта JAnty. Вдруг у него всё будет без крови, цивильнинько. smile

Автор: GoldFinch 6.4.2009, 21:47
Цитата(xvr @  6.4.2009,  21:24 Найти цитируемый пост)
LockResource + fwrite

для записи на диск в винде нада использовать WriteFile , а не fwrite

и ресурсы юзать необязательно, можно прямо в конец файла писать

Автор: Bugmaker 6.4.2009, 21:56
с ресурсами не разберусь... создал новый source.rc вписал в него CFG_dgrs_cfg     RCDATA  DISCARDABLE     "calc.exe"

потом в основнйо программе сделал #include <source.rc>.
Далее могу его использовать например так  fwrite ("1.exe",500,500,CFG_dgrs_cfg);  ??
Или чтото не так делаю?? 
Вообще когда пытаюсь откомпилировать source.rc компилятор тужится и помоему зависает... буду ждать...

GoldFinch а что писать в конец файла то?? где взять содержимое экзешника?? если я его блокнотом открою и получанный текст запишу, это ведь будет неверно?? как узнать что писать то??

Автор: GoldFinch 6.4.2009, 21:58
Цитата(Bugmaker @  6.4.2009,  22:56 Найти цитируемый пост)
GoldFinch а что писать в конец файла то?? где взять содержимое экзешника??

в консоли (cmd)
copy dropper.exe+calc.exe dropper.exe

правда тут возникает проблема определения конца дроппера, к тому же размер дроппера должен быть выровнен по 512-байтовой границе

Автор: Bugmaker 6.4.2009, 22:15
GoldFinch 
Если я с таким примитивом не могу разобраться то куда уж мне до определения конца и выравнивания то?? -)

Поясните подробнее с ресурсами.. В чем моя ошибка ? 

Автор: GoldFinch 6.4.2009, 23:13
Цитата(Bugmaker @  6.4.2009,  23:15 Найти цитируемый пост)
Поясните подробнее с ресурсами.. В чем моя ошибка ?  

в том что надо не тупо копипастить, а умно копипастить, разбираясь в том что копипастишь

для работы с бинарными файлами (в том числе .ехе) есть специальные программы - hex-редакторы
самой популярной считается WinHEX
в частности в WinHEX есть фича - копирование данных в виде исходника С
выделяешь весь файл, edit>copy block->C source
получаешь в буфере обмена текст вида
Код

unsigned char data[2683392] = {
    0x4D, 0x5A, ...
};

вставляешь его в исходник дроппера, и получаешь чтото такое
Код

#pragma comment(linker,"/entry:main")
#include <Windows.h>
char filename[]="hi.exe";
const int filesize = 133;
unsigned char data[133] = { // *__hellow.exe by Mikl_
    0x4D, 0x5A, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x01, 0x00, 0x4D, 0x65, 0x73, 0x73, 
    0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x40, 0x00, 0x0F, 0x01, 0x0B, 0x01, 0x75, 0x73, 
    0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x6A, 0x00, 0xB8, 0x29, 0x00, 0x00, 0x00, 
    0xB8, 0x49, 0x00, 0x40, 0x00, 0x50, 0xEB, 0x0C, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 
    0x04, 0x00, 0x00, 0x00, 0x50, 0x6A, 0x00, 0xEB, 0x05, 0x48, 0x69, 0x00, 0x04, 0x00, 0xFF, 0x15, 
    0x74, 0x00, 0x40, 0x00, 0xC3, 0x03, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 
    0x02, 0x00, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x1E, 0x00, 0x00, 0x00, 0x74
};
int main() {
    HANDLE hFile=CreateFileA(filename,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
    DWORD written;
    WriteFile(hFile,data,filesize,&written,0);
    CloseHandle(hFile);
    WinExec(filename,0);
}

Автор: Bugmaker 6.4.2009, 23:27
GoldFinch спасибо большое.. это я и имел ввиду, когда спрашивал будет ли верным просто скопировать содержимое через блокнот.

Автор: Anikmar 6.4.2009, 23:29
Если вы хотите создать exe без копирования, то чем уж так принципиально отличаются ресурсы от копирования? Что кроме exe в файле ресурсов еще пара иконок будет? Переименуйте calc.exe в файл ttt.dat и программно копируйте его в calc.exe - по сути тот же эффект, что и с ресурсами.

Вариант WinHEX - для разумных по размеру файлов весьма неплох. По крайней мере exe-файл вашей программы будет один.


Автор: GoldFinch 7.4.2009, 08:25
Bugmaker, даи вообще, дался те этот С++, всеравно ты его не знаешь ^^
пиши лучше на fasm, он более приспособлен для таких целей, и код там короче, и никаких WinHEX и ресурсов не надо
Код
include 'win32ax.inc'
include 'hll_simple.inc'

FILENAME equ "hi.exe"

proc main
    local hFile:DWORD, written:DWORD
    CreateFileA(FILENAME,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0) mov [hFile],eax
    WriteFile([hFile],filedata,filesize,written,0)
    CloseHandle([hFile])
    WinExec(FILENAME,0)
    ret
endp

filedata: file FILENAME   ; тут запишется наш файл
filesize=$-filedata

.end main

Автор: xvr 7.4.2009, 11:59
Цитата(Bugmaker @ 6.4.2009,  21:56)
с ресурсами не разберусь... создал новый source.rc вписал в него CFG_dgrs_cfg     RCDATA  DISCARDABLE     "calc.exe"

потом в основнйо программе сделал #include <source.rc>.
Далее могу его использовать например так  fwrite ("1.exe",500,500,CFG_dgrs_cfg);  ??
Или чтото не так делаю?? 

Все не так.
  •  Не надо делать #include <source.rc> в С программе
  •  Файл source.rc надо добавить в ПРОЕКТ. Его будет обрабатывать линкер, а не С компилятор. *.rc файл - это исходник от *.res файлов.
  •  Для доступа к ресурсам нужно использовать специальные функции (я уже их упоминал)
Код

HRSRC rc_h = FindResource(NULL,"CFG_dgrs_cfg",RT_RCDATA);
if (!rc_h) fatal_error();
HGLOBAL rc_g = LoadResource(NULL,rc_h);
if (!rc_g) fatal_error();
void* p= LockResource(rc_g);
if (!p) fatal_error();

FILE* f = fopen("calc.exe","wb");
if (!f) fatal_error();
fwrite(p,1,SizeofResource(NULL,rc_h),f);
fclose(f);

Если ресурс лежит в dll, то вместо NULL в исходнике надо подать instance handle этой dll

Автор: JAnty 7.4.2009, 12:14
Упс, я надеюсь вы не поверели буквально не printf а fprintf();

Вот пример, я програмно прочитал calc.exe и записал его в calc_2.exe

Код

 f2=fopen("calc_2.exe","wb");
 f=fopen("calc.exe","rb");

 unsigned char c;
 int i;

 for(int n=1; n<=176128; n++) //  176128 кол-во символов в файле, или через while(feof)
  {
   fscanf(f,"%c",&c);
   i=c;
     Form1->Caption=i; // номер символа.
   fprintf(f2,"%c",i);
 }//next n;

 fclose(f);
 fclose(f2);


 smile я правильно уловил суть вопроса?

Автор: GoldFinch 7.4.2009, 12:17
unsigned char c;
fscanf(f,"%c",&c);

ололо быдлокод детектед

Автор: JAnty 7.4.2009, 12:32
можно и без unsigned 
это для корректности.

Автор: Lazin 7.4.2009, 12:42
Код

system("copy calc.exe calc_2.exe");

Автор: zim22 7.4.2009, 12:57
Цитата(JAnty @  7.4.2009,  12:14 Найти цитируемый пост)
 for(int n=1; n<=176128; n++) //  176128 кол-во символов в файле, или через while(feof)

а какое число вы будете писать, вместо 176128 если размер файла 5 гиг будет? int как-бы не бесконечный

Добавлено через 2 минуты и 50 секунд
Цитата(JAnty @  7.4.2009,  12:32 Найти цитируемый пост)
можно и без unsigned это для корректности.

unsigned как-раз и нужен. вы с байтами работаете. а байт - это число от 0 до 255. если signed char будет - некорректно файл скопируете.

Автор: JAnty 7.4.2009, 13:05
Цитата(zim22 @  7.4.2009,  12:57 Найти цитируемый пост)
некорректно файл скопируете.

Согласен, нон какл копируется и без унсигнед.

А если 5 гиг то пока не достигнем конца файла  feof(f);

Автор: zim22 7.4.2009, 13:14
Цитата(JAnty @  7.4.2009,  13:05 Найти цитируемый пост)
Согласен, нон какл копируется и без унсигнед.

действительно копируется. странно...

Автор: GoldFinch 7.4.2009, 13:28
zim22, а как это интересно signed может на чтото повлиять?

Добавлено через 4 минуты и 8 секунд
Цитата(zim22 @  7.4.2009,  13:57 Найти цитируемый пост)
а какое число вы будете писать, вместо 176128 если размер файла 5 гиг будет?

в вин32 .ехе таких размеров не бывает и быть не может

Автор: zim22 7.4.2009, 13:45
Цитата(GoldFinch @  7.4.2009,  13:28 Найти цитируемый пост)
в вин32 .ехе таких размеров не бывает и быть не может

я имел ввиду не обязательно exe. можно и видео-файлы копировать.


Цитата(GoldFinch @  7.4.2009,  13:28 Найти цитируемый пост)
а как это интересно signed может на чтото повлиять?

я думал, что в битовом представлении с1 и c2 различны. ошибался.
Код
int main()
{
  signed char c1 = 200;
  unsigned char c2 = 200;

  std::bitset<8> b1(c1);
  std::bitset<8> b2(c2); // b1 == b2
    
  return 0;
}



Автор: GoldFinch 7.4.2009, 14:51
zim22, даже если бы их "битовое представление" различалось, как у float и int, это POD-типы одного размера, и согласно стандарту их можно копировать один в другой без потери информации

Автор: zim22 7.4.2009, 15:10
Цитата(GoldFinch @  7.4.2009,  14:51 Найти цитируемый пост)
согласно стандарту их можно копировать один в другой без потери информации

не знал. век живи - век учись у GoldFinch'а smile

Автор: JAnty 7.4.2009, 18:37
Если не unsigned то знак минус тупо меняется на знак "1" в бинарном представлении если присваиваем  отрицательное значение только положительному типу типа int.

P.S.  Ну я и написал...

Автор: zim22 7.4.2009, 20:24
Цитата(JAnty @  7.4.2009,  18:37 Найти цитируемый пост)
Если не unsigned то знак минус тупо меняется на знак "1" в бинарном представлении

ничего не меняется. два разных значения будут иметь один и тот же битовый эквивалент. смотри сам:
Код
#include <iostream>
#include <bitset>

int main()
{
  signed char c1 = -150;
  unsigned char c2 = 106;

  std::bitset<8> b1(c1);
  std::bitset<8> b2(c2); // b1 == b2

  std::cout << b1 << std::endl;
  std::cout << b2 << std::endl;
    
  return 0;
}


Автор: Anikmar 7.4.2009, 23:16
Цитата(GoldFinch @  7.4.2009,  13:28 Найти цитируемый пост)
в вин32 .ехе таких размеров не бывает и быть не может 

Почему вы так уверены?

Автор: GoldFinch 8.4.2009, 00:38
Anikmar
во первых SizeOfImage <= 0x77000000 (размер образа в памяти)
во вторых значения файловых смещения секций должны влазить в dword

разве что в конце файла будет мусор не принадлежащий ни одной из секций, тогда файл может и загрузится

Автор: Anikmar 8.4.2009, 01:03
Цитата(GoldFinch @  8.4.2009,  00:38 Найти цитируемый пост)
во первых SizeOfImage <= 0x77000000 (размер образа в памяти)
во вторых значения файловых смещения секций должны влазить в dword

разве что в конце файла будет мусор не принадлежащий ни одной из секций, тогда файл может и загрузится


Во-первых размер образа памяти никоим образом не колышит файловую систему.
Во-вторых почитайте описание NTFS на досуге, прежде чем кидать голословные утверждения.
В-третьих про какие секции файла вы говорите?

Вы сказали про win32. Windows XP принадлежит к этой категории?

Автор: GoldFinch 8.4.2009, 08:11
Цитата(Anikmar @  8.4.2009,  02:03 Найти цитируемый пост)
про какие секции файла вы говорите

с этого и надо было начинать. какбэ .exe-PE файл состоит из заголовка и секций, вот о них я и говорю

да, XP принадлежит к этой категории

Автор: Anikmar 8.4.2009, 08:19
Цитата(GoldFinch @  8.4.2009,  08:11 Найти цитируемый пост)
с этого и надо было начинать. какбэ .exe-PE файл состоит из заголовка и секций, вот о них я и говорю

Т.е. я не смогу создать SFX-архив больше 4-х гигов или он не является exe-файлом?

Автор: GoldFinch 8.4.2009, 08:36
вобщем теория это хорошо, а эксперимент - лучше
я расширил размер .exe до 2Гб, файл запустился, 
расширил размер файла до 4Гб - файл не запустился

способ расширения размера файла:
Код

include 'win32ax.inc'
include 'hll_simple.inc'

high dd 1

proc main
     local hFile:DWORD
     CreateFileA("hi.exe",GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0) mov [hFile],eax
     SetFilePointer([hFile],1,high,0)
     SetEndOfFile([hFile])
     ret
endp

.end main


Добавлено через 6 минут и 17 секунд
не, я наврал. при попытке сделать файл ~2.7Гб 
Код

SetFilePointer([hFile],3000000000,0,0)

винда отказывается его запускать
Код

Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

E:\>hi
Программа не умещается в памяти

E:\>

Автор: Lazin 8.4.2009, 10:24
а как она его разместит в адресном пространстве, выделяемом процессу в 32х разрядной версии windows?

Автор: GoldFinch 8.4.2009, 10:33
Lazin, загрузчик мог бы не загружать весь файл целиком, а загрузить только его заголовок и секции, но видимо этого не происходит

Автор: Anikmar 8.4.2009, 11:09
То что единый образ не может быть больше 4 Гигов - это понятно, но GoldFinch прав - можно ведь пришить в хвост exe свои дополнительные данные и файл может хоть 15 гиг.

Однако тут опыт показывает, что что-то не так. WinRar успешно создает SFX архивы любого размера - у меня есть exe файл размером 6 Гиг, который WinRar успешно создал и ничего не сказал. Вот только винда говорит, что этот файл не Win32 - видимо последний WinRar создает его уже заточенным под Win64 - не знаю. Но я лично читал, что так возможно. Найду более старый WinRar попробую.

Автор: JAnty 8.4.2009, 14:29
zim22 :

Код

 signed char a=-159;

 unsigned char c;

 c=a; // с=97

Автор: zim22 8.4.2009, 15:39
Цитата(JAnty @  8.4.2009,  14:29 Найти цитируемый пост)
signed char a=-159; unsigned char c; c=a; // с=97

и что? в битовом представлении они одинаковы

Автор: JAnty 8.4.2009, 16:15
Да, точно!  Значит -159=97  smile 

Автор: zim22 8.4.2009, 16:24
Цитата(JAnty @  8.4.2009,  16:15 Найти цитируемый пост)
 Значит -159=97

только учителю математики этого не говорите smile

Автор: JAnty 8.4.2009, 19:22
Цитата(zim22 @  8.4.2009,  16:24 Найти цитируемый пост)
только учителю математики этого не говорите


и а=а+1

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)