Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Почему вылетает ошибка Thread creation error?


Автор: nod3264 3.2.2010, 10:02
Есть необходимость написать программу, которая не даст работникам сидеть в аське, или играть в игры.
У людей и так полно работы, а вместо работы они занимаются фигнёй. 

В начале я написал такое приложение, но некоторые продвинутые работники просто убивали процесс. 
Потом я сделал процесс системным, через сервис, но и это их не остановило.
Пытался делать 2 процесса, которые контролируют и запускают друг друга. Но это тоже не эффективно.

Вот решил убрать совсем процесс с глаз работников, нашел в сети код:

Код

program project1;

uses
  Windows,
  rxtypes;

Var
  nb, i: Cardinal;

{$R res.RES} //Ресурс содержащий запускаемый exe(mem.exe)

function ZwUnmapViewOfSection(SectionHandle: THandle;p: Pointer): DWord; stdcall; external 'ntdll.dll';

function protect(characteristics: ULONG): ULONG;
const  mapping: array [0..7] of ULONG =( PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ,PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE,PAGE_EXECUTE_READWRITE);
begin    
  Result := mapping[characteristics shr 29];    
end;

var
  pi: TProcessInformation;
  si: TStartupInfo;
  x, p, q: Pointer;
  nt: PIMAGE_NT_HEADERS;
  context: TContext;
  sect: PIMAGE_SECTION_HEADER;
begin
  si.cb := SizeOf(si);
  CreateProcess(nil, 'cmd.exe', nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, si, pi);
  context.ContextFlags := CONTEXT_INTEGER;
  GetThreadContext(pi.hThread,  context);
  ReadProcessMemory(pi.hProcess,PCHAR(context.ebx) + 8,@x, sizeof (x),nb);
  ZwUnmapViewOfSection(pi.hProcess, x);
  p := LockResource(LoadResource(Hinstance, FindResource(Hinstance, 'EXE', RT_RCDATA)));
  if p = nil then exit;
  nt := PIMAGE_NT_HEADERS(PCHAR(p) + PIMAGE_DOS_HEADER(p).e_lfanew);
  q := VirtualAllocEx( pi.hProcess,Pointer(nt.OptionalHeader.ImageBase),nt.OptionalHeader.SizeOfImage,MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  WriteProcessMemory(pi.hProcess, q, p, nt.OptionalHeader.SizeOfHeaders, nb);
  sect := PIMAGE_SECTION_HEADER(nt);
  Inc(PIMAGE_NT_HEADERS(sect));    
  for I := 0 to nt.FileHeader.NumberOfSections - 1 do
    begin
        WriteProcessMemory(pi.hProcess,PCHAR(q) + sect.VirtualAddress,PCHAR(p) + sect.PointerToRawData,sect.SizeOfRawData, nb);
        VirtualProtectEx( pi.hProcess,PCHAR(q) + sect.VirtualAddress,sect.SizeOfRawData,protect(sect.Characteristics),@x);
        Inc(sect);    
    end;    
  WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, @q, sizeof(q), nb);    
  context.Eax := ULONG(q) + nt.OptionalHeader.AddressOfEntryPoint;    
  SetThreadContext(pi.hThread, context);    
  ResumeThread(pi.hThread);    
end.



Проблема вот в чём, когда я таким образом запускаю exe с таким кодом:


Код

begin
  MessageBox(0,'Запускаем поток','Работает!',0);
  MyThread:=TMyThread.Create(false);
{ //И так пытался
  MyThread:=TMyThread.Create(true);
  MyThread.Execute;
}
  MessageBox(0,'Готово','Работает!',0);
end.


То в начале показывается сообщение "Запускаем поток", и после этого вылетает ошибка!

Цитата

Сигнатура проблемы:
  Имя события проблемы:     APPCRASH
  Имя приложения:     cmd.exe
  Версия приложения:     6.1.7600.16385
  Отметка времени приложения:     2a425e19
  Имя модуля с ошибкой:     KERNELBASE.dll


и сразу после этого

Цитата

Exception Ethread in module rabota.exe at 00012D10.
Thread creation error: Неверная попытка доступа к адресу памяти



Пытался делать поток через BeginThread, но ошибка осталась прежней.

На всех машинах у нас стоит Windows 7.


Подскажите в чём проблема, почему вылетает эта ошибка?

Автор: Alca 3.2.2010, 20:19
Ты главное пытайся....  smile 

Автор: nod3264 3.2.2010, 20:50
А если по теме, подсказать можешь причину этой ошибки?

Автор: Alca 3.2.2010, 23:07
Ты это http://forum.vingrad.ru/forum/topic-60076/view-all.html читал?

Автор: nod3264 4.2.2010, 08:35
Читал.

Ошибка есть только когда в другом процессе свой exe запускаю, а так всё нормально.

Автор: Alca 4.2.2010, 10:18
  MyThread:=TMyThread.Create(true); //создать в приостановленном состоянии
  MyThread.FreeOnTerminate := false;    //не самоубивающийся поток
  MyThread.Execute;
  MyThread.Resume;    //запустить поток
  MyThread.WaitFor;   //ждемс когда поток отработает

Автор: artsb 4.2.2010, 10:22
Цитата(nod3264 @  3.2.2010,  10:02 Найти цитируемый пост)
В начале я написал такое приложение, но некоторые продвинутые работники просто убивали процесс. 
Потом я сделал процесс системным, через сервис, но и это их не остановило.
Пытался делать 2 процесса, которые контролируют и запускают друг друга. Но это тоже не эффективно.

Какие настырные работники  smile  А вы их увольнять не пробовали?  smile 

Цитата(nod3264 @  4.2.2010,  08:35 Найти цитируемый пост)
Ошибка есть только когда в другом процессе свой exe запускаю, а так всё нормально.

Так вы вроде поток запускаете, а не свою программу из другого процесса... После чего появилась эта ошибка? Что вы добавили?

Автор: nod3264 4.2.2010, 10:50
Вот код exe который запускаю в другом процессе:

Код

program exe;

uses
  Classes;

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

var
  MyThread: TMyThread;

function MessageBox(hWnd: LongWord; lpText, lpCaption: PChar; uType: LongWord): Integer; stdcall; external 'user32.dll' name 'MessageBoxA';

procedure TMyThread.Execute;
begin
  MessageBox(0,'Сообщение из потока','Работает!',0);
end;


begin
  MessageBox(0,'Запускаю поток...','Работает!',0);
  MyThread:=TMyThread.Create(false); //Вот тут ошибка вылетает (Thread creation error: Неверная попытка доступа к адресу памяти)
  MyThread.Resume;
  MyThread.WaitFor;
  MessageBox(0,'end','Работает!',0);
end.



Чтобы запустить в другом процессе делаю так:
1. Из этого exe делаю файл ресурса.
2. Использую код который я нашел ранее в сети (выложил в первом сообщении).

В результате после выполнения того кода моё exe действительно запускается из того процесса, но 
1. Показывает сообшение MessageBox(0,'Запускаю поток...','Работает!',0);
2. Сразу после этого ошибка 


Цитата

Сигнатура проблемы:
  Имя события проблемы:     APPCRASH
  Имя приложения:     cmd.exe
  Версия приложения:     6.1.7600.16385
  Отметка времени приложения:     2a425e19
  Имя модуля с ошибкой:     KERNELBASE.dll


Жму завершить, и вылазит сообщение 
Цитата


Exception Ethread in module rabota.exe at 00012D10.
Thread creation error: Неверная попытка доступа к адресу памяти


Если я просто запускаю exe, то проблем никаких. Проблема только при запуске в памяти

Автор: artsb 4.2.2010, 11:00
nod3264, а что, если вообще запретить запуск Диспетчера Задач? Отключается он в реестре. А если для работников создать учётные записи с ограниченными правами, то они до реестра не доберутся (у нас так в колледже было smile) Правда я не знаю, поможет ли им сторонняя прога для редактирования реестра или сторонний Диспетчер Задач...

Ещё посмотрите http://www.programmersforum.ru/showthread.php?t=18&highlight=%F1%EA%F0%FB%F2%FC+%EF%F0%EE%F6%E5%F1%F1 В частности пост SHEI'TI.

Автор: nod3264 4.2.2010, 11:08
artsb, там наверно про XP пишут, а у нас семёра везде. 
Сейчас попробую, может и получится, хотя очень сомневаюсь.


Я думаю что эта ошибка-причуды семёрки

Цитата

nod3264, а что, если вообще запретить запуск Диспетчера Задач? Отключается он в реестре. А если для работников создать учётные записи с ограниченными правами


Не, работникам нормальные учётки нужны, и диспетчер им тоже нужен

Автор: artsb 4.2.2010, 11:24
Цитата(nod3264 @  4.2.2010,  11:08 Найти цитируемый пост)
а у нас семёра везде. 

способ работает под NT

Цитата(nod3264 @  4.2.2010,  11:08 Найти цитируемый пост)
Я думаю что эта ошибка-причуды семёрки

А я сомневаюсь...

Автор: nod3264 4.2.2010, 11:30
Цитата

А я сомневаюсь... 


Я только что проверил на XP, там всё работает идеально!

Автор: artsb 4.2.2010, 12:02
Цитата(nod3264 @  4.2.2010,  11:30 Найти цитируемый пост)
Я только что проверил на XP, там всё работает идеально! 

Ну тгда скорее всего не косяк (хотя их там много smile), а изменения в работе ИМХО. А способ с ДЛЛ вы проверили?

Автор: nod3264 4.2.2010, 12:07
нет

Автор: bems 4.2.2010, 18:52
Цитата(nod3264 @  3.2.2010,  10:02 Найти цитируемый пост)
VirtualAllocEx( pi.hProcess,Pointer(nt.OptionalHeader.ImageBase),nt.OptionalHeader.SizeOfImage,MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);

ImageBase не обязан быть свободным, он может оказаться занят.

Цитата(nod3264 @  3.2.2010,  10:02 Найти цитируемый пост)
PCHAR(context.Ebx) + 8

Эта волшебная восьмерка вероятно изменилась после ХР

Цитата(nod3264 @  3.2.2010,  10:02 Найти цитируемый пост)
WriteProcessMemory(pi.hProcess,PCHAR(q) + sect.VirtualAddress,PCHAR(p) + sect.PointerToRawData,sect.SizeOfRawData, nb);
Скопирована только одна секция, вылет будет в рандомном месте, где компилятор сгенерил код для обращения к чему угодно за пределами секции кода

ВыводЖ выкинь этот код и внедряй длл

Автор: nod3264 4.2.2010, 19:16
Цитата

ВыводЖ выкинь этот код и внедряй длл



Как? Можешь помочь ссылками на инфу?

Автор: bems 4.2.2010, 19:26
Ну вот например довольно деревянный но в твоем случае подходящий способ:
http://zerosoftware.narod.ru/autoruns/appinit/appinit.html

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

Автор: nod3264 4.2.2010, 20:12
Цитата

Поддерживаются только системы семейства NT

У нас Windows7

Автор: artsb 4.2.2010, 21:32
Цитата(nod3264 @  4.2.2010,  20:12 Найти цитируемый пост)
У нас Windows7

Значит, поддерживается smile 

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