Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Кодерские tips and tricks (https://forum.antichat.xyz/showthread.php?t=27346)

TaNkist 16.11.2006 15:48

Кодерские tips and tricks
 
Кодерские tips’n’tricks

В данной теме делимся программерскими трюками. Это могут быть советы по оптимизации, нестандартные приемы, интересные (но не слишком большие) куски кода. Не стоит превращать тему в свалку исходников, выбирайте наиболее интересные и полезные участки кода. Желательно откомметировать трюк, чтобы всем было понятно.
Delphi
Оптимизация

[Передача аргументов] Никогда не передавай функции в качестве параметра структуру, лучше передавать указатель на нее
Код:

//Ни в коем случае не делай так.
Procedure code (Data:TStructure);
//Правильный вариант
Procedure code (PData:PStructure); //гда PStructure = ^TStrucrure

Старайся передавать своим функциям не более трех параметров, т.к. они передаются через регистры (по соглашению fastcall, принятом по умолчанию в Delphi), а все остальные через стек.
[Функции - инварианты] Довольно распространенная ошибка программистов – присутствие функций - инвариантов в цикле.
Код:

//Неоптимизированный вариант
While i<= lstrlen(str) do
Begin
X:=x+ord(str[i]);
Inc(i);
End;

Очевидно, что длина str не меняется, но компилятор считает, что все, что передается по ссылке сожжет быть изменено, и lstrlen вычисляется много раз. Оптимизированный вариант выглядит так.
Код:

//Так лучше
N:=lstrlen(str);
While i<= n do
Begin
X:=x+ord(str[i]);
Inc(i);
End;

[Экономия памяти] Когда класс располагается в памяти, то между полями появляются пустые ячейки памяти. Это происходит потому, что Delphi, оптимизируя код, каждое поле располагает от предыдущего со сдвигом в 4 байта.
Код:

// Неоптимизированный вариант
TMyClass = class
  private
    field1: boolean;//1 байт
    field2: longint; //4 байт
    field3: char; //1 байт
    field4: string; //4 байт
    field5: byte; //1 байт
    field6: integer; //4 байт
    field7: byte; //1 байт
  public
    procedure code;
end;

Реально этот экземпляр класса будет занимать 28 байт. Если мы изменим порядок полей, то сможем добиться уменьшения размера до 16 байт. В нашем примере после field1 размером 1 байт идет field2 размером 4 байта, значит, мы теряем 3 байта на выравнивание. Если же размер field2 не превышал 3 байт, то Delphi не стал бы выравнивать, а поместил бы это поле сразу после первого.
Код:

// Оптимизированный вариант
TMyClass = class
  private
    field1: boolean; //1 байт
    field3: char; //1 байт
    field5: byte; //1 байт
    field7: byte; //1 байт
  field2: longint; //4 байт
    field4: string; //4 байт
    field6: integer; //4 байт
  public
    procedure code;
end;

[Компиляция без RTL (Run Time Library)] Как известно минимальный размер скомпилированной в Delphi программы с настройками по умолчанию равен 13,5 Кб. Виной тому принудительно подключаемая Delphi RTL, в которой реализованы некоторые возможности языка Delphi.
Для уменьшения размера скомпилированных прог исправим модели System.pas и SysInit.pas, удалив все «лишнее». Затем перекомпилируем их и полученные dcu-файлы поместим в папку с прогой.
Минимальный System.pas
Код:

unit System;

interface

procedure _HandleFinally;

type
 TGUID = record
  D1: LongWord;
  D2: Word;
  D3: Word;
  D4: array [0..7] of Byte;
 end;

 PInitContext = ^TInitContext;
 TInitContext = record
    OuterContext:  PInitContext; 
    ExcFrame:      Pointer;         
    InitTable:      pointer;   
    InitCount:      Integer;         
    Module:        pointer;     
    DLLSaveEBP:    Pointer;
    DLLSaveEBX:    Pointer;
    DLLSaveESI:    Pointer; 
    DLLSaveEDI:    Pointer; 
    ExitProcessTLS: procedure;   
    DLLInitState:  Byte;           
 end;

implementation

procedure _HandleFinally;
asm
end;

end.

Минимальный SysInit.pas
Код:

unit SysInit;

interface
procedure _InitExe;
procedure _halt0;
procedure _InitLib(Context: PInitContext);

var
  ModuleIsLib: Boolean;       
  TlsIndex: Integer = -1;     
  TlsLast: Byte;

const
  PtrToNil: Pointer = nil; 

implementation

procedure _InitLib(Context: PInitContext);
asm
end;

procedure _InitExe;
asm
end;

procedure _halt0;
asm
end;
end.

Компиляция
Код:

Dcc32.exe – Q System.pas SysInit.pas –M –Y –Z -$D- -O
Некоторые трюки

[Обмен] Обмен значений между двумя переменными без привлечения третьей.
Код:

x:=x xor y;
y:=y xor x;
x:=x xor y;


_Great_ 16.11.2006 16:04

Оптимизация выходного файла в Microsoft Visual C++.
Параметры линкера для уменьшения размера:
- объединение секций
Код:

/MERGE:.data=.text /MERGE:.rdata=.text
- можно еще снизить выравнивание, например, задать 512 байт или 32 байта
Код:

/ALIGN:32
или
Код:

/ALIGN:512
соответственно.
- смена точки входа
Код:

/ENTRY:main
или
Код:

/ENTRY:WinMain
для консольного и виндового приложения соответственно. Уменьшает размер, т.к. тогда линкер не пихает в экзешник код стартовой функции mainCRTStartup (WinMainCRTStartup). Только надо помнить, что параметры main (WinMain) в этом случае не будут нести никакого смысла, аргументы командной строки придется получать явно через API GetCommandLine().
- еще можно убрать нафиг CRT или линковать ее динамически:
Код:

/NODEFAULTLIB msvcrt.lib
С учетом всех рекомендаций:
Код:

#include <windows.h>
#pragma comment(linker, "/NODEFAULTLIB /MERGE:.data=.text /MERGE:.rdata=.text /ALIGN:512 /ENTRY:WinMain")

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
        MessageBox(0, "Hello, World!", "Tiny application", MB_ICONINFORMATION);
        return 0;
}

Результат - имеет хелловорлд размером 1к, состоящим из заголовка экзешника и одной секции.
Дизассемблерный листинг точки входа не содержит ни одного лишнего байта:
Код:

00400230 >/$ 55            PUSH EBP
00400231  |. 8BEC          MOV EBP,ESP
00400233  |. 6A 40          PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00400235  |. 68 08024000    PUSH tiny.00400208                      ; |Title = "Tiny application"
0040023A  |. 68 1C024000    PUSH tiny.0040021C                      ; |Text = "Hello, World!"
0040023F  |. 6A 00          PUSH 0                                  ; |hOwner = NULL
00400241  |. FF15 00024000  CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
00400247  |. 33C0          XOR EAX,EAX
00400249  |. 5D            POP EBP
0040024A  \. C2 1000        RETN 10

UPD: Можно снизить выравнивание до 16-и байт, притворившись, что мы собираем драйвер:
/ALIGN:16 /DRIVER
это нужно вписать в настройки проекта, в #pragma comment(linker) это не прокатит

TaNkist 18.11.2006 21:28

Delphi
Чтобы во время выполнения циклов, не происходил эффект зависания, нужно в теле цикла вставить
Код:

Application.ProcessMessages;
Эффект зависания происходит из-за того, что Windows ждет пока накопятся задания в очереди, а не выполняет их сразу. Application.ProcessMessages заставляет винду выполнить все задачи, которые накопились в данный момент.

W!z@rD 19.11.2006 10:24

в VCL (delphi) есть "перехват" закрытия формы
OnCloseQuery (где canclose boolean типа который и дает "разрешение" на закрытие формы)...

TaNkist 22.11.2006 14:14

Экстремально маленький Hello Word! на Delphi.

Собирать исполняемый файл линкером от Microsoft. К сожалению, майкрософтовкий линкер понимает только COFF и Intel OMF, наотрез отказываясь работать с Borland OMF. Delphi же, начиная с третьей версии, перешла с формата Intel OMF на Borland OMF. Поэтому компилировать придется компилятором от Delphi 3.
Пример минимального HelloWord.
Код:

Unit HelloWord;
Interface
Procedure Start;
Implementation
Function MessageBoxA(hWnd:cardinal; IpText, IpCaption:Pchar; uType:Cardinal): Integer; stdcall; external ‘user32.dll’ name ‘_MessageBoxA@16’;
Procedure Start;
Begin
        MessageBoxA(0,’Hello word!’,nil,0);
End;
End.

Ти модуля Unit нужен для того, чтобы компилятор сгенерировал в объектном файле символьные имена объявленных процедур.
Компилируем:
Dcc32.exe –JP -$A-,B-,C-,D-,G-,H-,I-,J-,L-,M-,O+,P-,Q-,R-,T-,U-,V-,W+,X+,Y- HelloWord.pas
Открываем файл HelloWord.obj в HEX-редакторе и смотрим во что превратилась наша точка входа. Допустим Start$wwrv. Теперь выполняем сборку
Link.exe /ALIGN:32 /FORCE:UNRESOLVED /SUBSYSTEM:WINDOWS /ENTRY:Start$wwrv HelloWord.obj user32.lib /out:Hello.exe
В результате имеем файл размером 832 байта.

W!z@rD 25.11.2006 22:08

в библиотеках (касается Delphi) если передаешь string данные от лучше заюзать переменную типа ShortString либо добавить ShareMem в раздел Uses... Имхо 1 лучше...
а если явно передаваемые данные string (например Edit1.Text), преобразуй ShortString(Edit1.Text);
таким образом можно пребразовывать не только ShortString, но допустим и из string в PChar=> pchar(edit1.text)

_Great_ 08.12.2006 13:43

Вот нашел несколько полезных советов для M$ Visual Studio.
Кому интересно - оригинал тут
Я приведу собственный перевод с моими комментариями.

1. Учим Visual Studio раскрывать структуры и классы в отладчике
Редактируем файл \Program Files\Microsoft Visual Studio\Common\MSDev98\Bin. Его формат можно определить методом тыка, посмотрев уже существующие строки. (Там все не так уж и сложно. В начале файла есть немаленький комментарий про синтаксис. Насколько я понял, просто вместо древовидной структуры объекта или структуры будет показываться одно значение. Например, для CString - m_pchData - Прим. Great).

2. Добавляем слова для подсветки.
Если создать файл usertype.dat в каталоге \Program Files\Microsoft Visual Studio\Common\MSDev98\Bin со словами по одному на строчку, то эти слова студия будет выделять синим цветом как ключевые. (Я уже добавил туда main и WinMain для удобства - Прим. Great).

3. Как использовать расширение *.cc для C++
Нужно произвести следующие изменения в реестре:
Цитата:

HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0 \Text Editor\Tabs/Language Settings\C/C++
FileExtensions=cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc; rc2;cc;cp

HKEY_USERS\S-1-5-21-1219703950-274334628-1532313055-1335\Software\Microsoft\DevStudio\6.0\Build System\Components\Platforms\Win32 (x86)\Tools\32-bit C/C++ Compiler for 80x86
Input_Spec=*.c;*.cpp;*.cxx,*.cc,*.cp

HKEY_USERS\S-1-5-21-1219703950-274334628-1532313055-1335\Software\Microsoft\DevStudio\6.0\Build System\Components\Tools\<Component 0x3>
Input_Spec=*.c;*.cpp;*.cxx;*.cc;*.cp
и добавить флаг /Tp к флагам компилятора в настройках проекта

4. Как закрепить меню.
В Visual Studio панель меню перемещаемая (об этом говорят две полосы слева). Если это мешает, это можно убрать, выставив галочку "Use screen reader compatible menus" в диалоговом окне Tools -> Options -> закладка Worspace

5. Напоминания при компиляции
Если у тебя плохо с памятью :) и тебе сложно запомнить, например, что вот тот кусок кода в финальной версии желательно убрать или что в этом коде содержится некритичная проблема, можно сделать себе напоминание:
Код:

#define Stringize( L ) #L
#define MakeString( M, L ) M(L)
#define $Line MakeString( Stringize, __LINE__ )
#define Reminder __FILE__ "(" $Line ") : Reminder: "

использовать:
#pragma message(Reminder "Fix me!")

В результате компилятор сгенерирует при компиляции сообщение:
Цитата:

Compiling...
seh.cpp
H:\Progs\seh\seh.cpp(163) : Reminder: Fix me!
Linking...

seh.exe - 0 error(s), 0 warning(s)
6. Как сделать вручную точку останова
Просто поставить код
Код:

__asm int 3;
При нажатии на F5, когда выполнение дойдет до этого места, процессор сгенерирует исключение EXCEPTION_BREAKPOINT, отладчик его поймает и выведет сообщение - User breakpoint called from code at 0x...

7. Отладочные значения в различных областях памяти программы
0xCDCDCDCD Память выделена в куче, не инициализирована
0xDDDDDDDD Память, выделенная в куче, уже освобождена
0xFDFDFDFD Заполнитель NoMansLand записывается у границ участка памяти для контроля распространенного типа ошибки выхода за границы массива и переполнения. После затирании это указатели при освобождлении этой памяти free/delete выдаст диалоговое окно: DAMAGE: after ТИП block (#номер) at 0xадрес., где ТИП - обычно Normal - тип освобождаемого участка, номер - номер блока.
Пример неправильного кода:
Код:

        char* a = new char[2];
        strcpy(a, "aaaaaaaaaaaaaaaaaaaaa");
        delete a;

Во время выполнения delete отладочная сборка программы выдаст окно "DAMAGE: after Normal block (#55) at 0x00430030".
0xCCCCCCCC Выделено в стеке, не инициализировано

8. Предопределенные псевдопеременные во время отладки
В окно Watch можно добавить следующие "переменные":
@err - последняя ошибка (GetLastError)
@tib - адрес Thread Information Block потока
@clk - время выполнения программы (мс)

9. Просмотр указателей как массивов
Обычно, если добавить в окно Watch переменную типа char*, она покажется как строка, а не как массив. Чтобы посмотреть отдельные элементы массива (например, чтобы узнать ASCII-код символа из этой строки), надо добавить в Watch выражение переменная,длина, где переменная - переменная указательного типа, длина - за массив какой длины отладчик ее должен считать.
Например, пусть объявлен char* str;
Выражение str,10 нам покажет всю строку + отдельно как массив ее первые 10 символов (в массиве - индексы 0-9).
Выражение ((char*)&main),100 покажет нам первые 100 байт машинного кода функции main

10. Вызов программных функций во время отладки
Если у тебя есть функция, например,
Код:

int function()
{
  return 100*2;
}

а тебе хочется посмотреть, что бы она возвратила во время отладки, если бы стоял ее вызов в коде - нет проблем! Просто добавляем в окно Watch выражение function() и сразу там появится значение 200

11. Именование потоков при отладке
Следущий код содержит функцию, позвляющую назвать поток с указанным ID'ом своим именем
Код:

#define MS_VC_EXCEPTION 0x406d1388
typedef struct tagTHREADNAME_INFO
{
        DWORD dwType; // must be 0x1000
        LPCSTR szName; // pointer to name (in same addr space)
        DWORD dwThreadID; // thread ID (-1 caller thread)
        DWORD dwFlags; // reserved for future use, most be zero
} THREADNAME_INFO;
void SetThreadName(DWORD dwThreadID, LPCTSTR szThreadName)
{
        THREADNAME_INFO info;
        info.dwType = 0x1000;
        info.szName = szThreadName;
        info.dwThreadID = dwThreadID;
        info.dwFlags = 0;
        __try
        {
                RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info);
        }
        __except (EXCEPTION_CONTINUE_EXECUTION)
        {
        }
}

Имя потока появится в окне Debug->Threads.

_Great_ 05.01.2007 12:55

Не совсем в тему, но все же. Поиск базы длл по ее имени в адресном пространстве другого процесса (аналог GetModuleHandle, но для др. адресного пространства).
Может, кому понадобится. Писал я по просьбе протеуса ну и соотв. там мои норкоманские идеи :)
Итак, че же для этого я сделал.
Ищем первый поток процесса. С помощью GetThreadSelectorEntry получаем запись LDT по селектору FS = 0x3b. Открываем Thread Environment Block, из него Process Environment Block, из него - структуру данных загрузчика (все это через ReadProcessMemory), потом проходимся по списку модулей.

Код:

        const DWORD FS = 0x3B;
        DWORD ownerProcessId = 38056;

        // Open process
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, ownerProcessId);
        if(!hProcess)
                return printf("Cannot open process\n");

        // Find thread
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
        THREADENTRY32 te = {sizeof(te)};
        Thread32First(hSnapshot, &te);
        DWORD threadId = 0;
        do
        {
                if(te.th32OwnerProcessID == ownerProcessId)
                        threadId = te.th32ThreadID;
        }
        while(Thread32Next(hSnapshot, &te));
        if(!threadId)
                return printf("No threads for specified process id\n");

        // Get FS base
        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, threadId);
        if(!hThread)
                return printf("Cannot open thread\n");

        LDT_ENTRY fs_entry;
        GetThreadSelectorEntry(hThread, FS, &fs_entry);

        DWORD fs_base = fs_entry.BaseLow | (fs_entry.HighWord.Bytes.BaseMid<<16) | (fs_entry.HighWord.Bytes.BaseHi<<24);

        // Read modules list
        TEB teb;
        DWORD read;
        if(!ReadProcessMemory(hProcess, (LPCVOID) fs_base, &teb, sizeof(teb), &read))
                return printf("Can't read process memory for TEB, %d bytes read\n", read);

        PEB peb;
        if(!ReadProcessMemory(hProcess, (LPCVOID) teb.Peb, &peb, sizeof(peb), &read))
                return printf("Can't read process memory for PEB, %d bytes read\n", read);

        PEB_LDR_DATA pld;
        if(!ReadProcessMemory(hProcess, (LPCVOID) peb.LoaderData, &pld, sizeof(pld), &read))
                return printf("Can't read process memory for PEB_LDR_DATA, %d bytes read\n", read);

        LDR_MODULE entry;
        if(!ReadProcessMemory(hProcess, (LPCVOID) pld.InInitializationOrderModuleList.Flink, &entry, sizeof(entry), &read))
                return printf("Can't read process memory for LDR_MODULE, %d bytes read\n", read);

        WORD wbuffer[20];
    char buffer[1024];

    // Walk the list
    do
    {
        // Print the name
                if(!ReadProcessMemory(hProcess, (LPCVOID) entry.BaseDllName.Buffer, &wbuffer, sizeof(wbuffer), &read))
                        return printf("Can't read process memory for wbuffer in loop, %d bytes read\n", read);
               
        WideCharToMultiByte(CP_ACP, 0, wbuffer, -1, buffer, sizeof(buffer), 0, 0);
        printf("%s\t[0x%08x]\n", buffer, entry.BaseAddress);

        // Next
                if(!ReadProcessMemory(hProcess, (LPCVOID) entry.ModuleList.Flink, &entry, sizeof(entry), &read))
                        return printf("Can't read process memory for LDR_MODULE in loop, %d bytes read\n", read);
    }
    while(entry.ModuleList.Flink != pld.InInitializationOrderModuleList.Flink);

        CloseHandle(hThread);
        CloseHandle(hProcess);
        CloseHandle(hSnapshot);


Cr4sh 16.02.2007 16:15

Цитата:

Сообщение от _Great_
Не совсем в тему, но все же. Поиск базы длл по ее имени в адресном пространстве другого процесса (аналог GetModuleHandle, но для др. адресного пространства).

уж0с... вот то же самое, но без изврата =/
Код:

DWORD RemoteGetModuleHandle(char *name, DWORD dwPid)
{
        MODULEENTRY32 m = {sizeof(m)};
        DWORD dwRet = 0;

        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid);
        if (hSnap == INVALID_HANDLE_VALUE)
                return NULL;

        if (!Module32First(hSnap, &m))
                return NULL;
        do {
                if (!lstrcmpi(m.szModule, name))
                  {
                        dwRet = m.modBaseAddr;
                          break;
                  }
        } while (Module32Next(hSnap, &m));

        CloseHandle(hSnap);
       
        return dwRet;
}


_Great_ 16.02.2007 18:38

Cr4sh, нуууууу ))) так не прикольно :)) Прикольно вручную анализировать ))
Хотя изобретать велосипед, конечно, тоже не стоит )

Cr4sh 16.02.2007 21:19

Цитата:

Cr4sh, нуууууу ))) так не прикольно ) Прикольно вручную анализировать ))
зато я больше чем уверен, что этот код будет стабильно работать на всей линейке от NT 4.0 и до Висты ;))

_Great_ 30.04.2007 20:01

Перенос программы в другое адресное пространство.

Был замечательный метод по инжекту кода в другую программу - вся наша программа постранично копировалась в чужое АП (адресное пространство) по тем же адресам со всеми заголовками, секциями и прочим.

Все было бы хорошо, пока там память свободна. Если там память занята, метод не предусматривал решения в этом случае.

Предлагаю модификацию: поиск наилучшего достаточного места в другом АП, копирование программы, коррекция фиксапов:

Код:

// Get VA
#define RVATOVA( base, offset )(((DWORD)(base) + (DWORD)(offset)))

// Move program's memory
void __CopyMemoryAcrossProcesses( HANDLE hProcess, char* pMemLocal, char* pMemRemote )
{
        DWORD dwOldProt, dwNumBytes, i;
        MEMORY_BASIC_INFORMATION mbi;
       
        VirtualQueryEx(hProcess, pMemRemote, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
        while (mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0)
        {
                if (!(mbi.Protect & PAGE_GUARD))
                {
                        for (i = 0; i < mbi.RegionSize; i += 0x1000)
                        {
                                VirtualProtectEx(hProcess, pMemRemote + i, 0x1000,PAGE_EXECUTE_READWRITE, &dwOldProt);
                                WriteProcessMemory(hProcess, pMemRemote + i, pMemLocal + i, 0x1000, &dwNumBytes);
                        }
                }
                pMemLocal += mbi.RegionSize;
                pMemRemote += mbi.RegionSize;
                VirtualQueryEx(hProcess, pMemRemote, &mbi, sizeof(MEMORY_BASIC_INFORMATION));       
        }
}

bool TransferProgram(HANDLE hProcess)
{
        HMODULE g_module = GetModuleHandle(0);
        VirtualFreeEx(hProcess, g_module, 0, MEM_RELEASE);
       
        DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(g_module) + ((PIMAGE_DOS_HEADER)(g_module))->e_lfanew +
                sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;

        char *pMem = (char *)VirtualAllocEx(hProcess, g_module, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if(pMem == NULL) return FALSE;

        __CopyMemoryAcrossProcesses( hProcess, (char*) g_module, pMem );

        return true;
}

DWORD TransferProgramEx(HANDLE hProcess)
/*
 Return value: image base delta, -1 on error
*/
{
        HMODULE hmodule = GetModuleHandle(0);
        DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(hmodule) + ((PIMAGE_DOS_HEADER)(hmodule))->e_lfanew +
                sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;

        MEMORY_BASIC_INFORMATION mbi = {0};
        VirtualQueryEx( hProcess, hmodule, &mbi, sizeof(mbi) );

        LPVOID Allocated;

        // Memory isn't free, relocate
        if( mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0 )
        {
__try_relocate:
                LPVOID DesiredAddress = hmodule;
                *(DWORD*)&DesiredAddress += mbi.RegionSize;

                for(;;)
                {
                        Allocated = VirtualAllocEx( hProcess, DesiredAddress, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
                        if( Allocated )
                                break;
                        *(DWORD*)&DesiredAddress += dwSize;
                }
        }
        else
        {
                Allocated = VirtualAllocEx( hProcess, hmodule, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
                if( !Allocated )
                        goto __try_relocate;
        }

        // move memory
        __CopyMemoryAcrossProcesses( hProcess, (char*) hmodule, (char*) Allocated );

        DWORD ImageBaseDelta = (DWORD)Allocated - (DWORD)hmodule;

        // Nonzero imagebase delta
        if( ImageBaseDelta )
        {
                // Apply fixups
                typedef struct
                {
                        WORD        Offset:12;
                        WORD        Type:4;
                } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;

                PIMAGE_OPTIONAL_HEADER poh =
                        (PIMAGE_OPTIONAL_HEADER)(
                                (DWORD)hmodule
                                + ((PIMAGE_DOS_HEADER)hmodule)->e_lfanew
                                + sizeof(IMAGE_NT_SIGNATURE)
                                + sizeof(IMAGE_FILE_HEADER)
                        );

                // No fixups?
                if( !poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress )
                {
                        VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
                        VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE  );
                        return -1;
                }

                PIMAGE_BASE_RELOCATION Reloc = (PIMAGE_BASE_RELOCATION) RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, hmodule);
                int i = 0;

                // Process fixups
                for( PIMAGE_FIXUP_ENTRY Fixup = (PIMAGE_FIXUP_ENTRY)( (DWORD)Reloc + sizeof(IMAGE_BASE_RELOCATION) );
                    (DWORD)Fixup < (DWORD)Reloc + Reloc->SizeOfBlock -2;
                        Fixup ++, i ++
                                )
                {
                        if( Fixup->Type == IMAGE_REL_BASED_HIGHLOW )
                        {
                                DWORD* Patch = (DWORD*)RVATOVA( Reloc->VirtualAddress + Fixup->Offset, Allocated );
                               
                                DWORD t, r;
                                BOOL b = 1;

                                // correct fixup
                                b &= ReadProcessMemory( hProcess, Patch, &t, 4, &r );
                                t += ImageBaseDelta;
                                b &= WriteProcessMemory( hProcess, Patch, &t, 4, &r );

                                if( !b )
                                {
                                        // smth wrong
                                        VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
                                        VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE  );
                                        return -1;
                                }
                        }
                        else
                        {
                                // unsupported fixup type
                                VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
                                VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE  );
                                return -1;
                        }
                }
        }

        return ImageBaseDelta;
}

TransferProgram - старый вариант
TransferProgramEx - моя модификация

Использовать примерно так:

Код:

        DWORD ImageBaseDelta = TransferProgramEx( hProcess );

        switch(ImageBaseDelta)
        {
        case -1:
                return printf("Cannot copy body\n"), 0;

        case 0:
                printf("Program copied at the same addresses\n");
                break;

        default:
                printf("Program relocated (delta = 0x%08x)\n", ImageBaseDelta);
                break;
        }

        DWORD thID;
        HANDLE hTh;

        hTh = CreateRemoteThread( hProcess, 0, 0, (LPTHREAD_START_ROUTINE)((char*)RemoteThread+ImageBaseDelta), 0, 0, &thID);
        WaitForSingleObject( hTh, INFINITE );


gevara 04.05.2007 00:52

_Great_
Вообще для бряка я создаю макрос
#define __INT3 __asm int 3;
более наглядней.

Удобно при написании дров использовать Int 3 причём с опкодом CC, а не с CD 03. тем более что некоторые ядерные отладчики имеют функцию: заменить все int3 (0xCC) на nop (0x90). НО ,как я понимаю, в VC такой возможности нет. обидно.
------------------------------------------------------------------------
Иногда функция должна возвращать результат своей работы (допустим ошибку), который нужно показать юзеру. Удобно делать следующим образом:

PCHAR func(...)
{
..
return "ERROR";
...
return "STATUS_SUCCESS";
}
------------------------------------------------------------------------
Что касается сишных функций - тож можно передавать параметры через регистры. достаточно при объявлении указать __fastcall :

DWORD __fastcall func1(arg1,arg2,...)
{
...
}
------------------------------------------------------------------------
Допустим, необходимо проверить 4 символа в строке.

PCHAR str1;
ULONG i;
...
if ( (str[i] == 'd') && (str[i+1]== 'c') &&...) ...

НО лучше так:

if ( *(PDWORD)&str1[i] == 'abcd' ) ...

только нужно учитывать, что компилятор переворачивает символы в строке.

slesh 14.05.2007 11:49

Способ конвертировать любые типы практически в любые другие.
К примеру если необходимо загнать в массив значение переменной типа dword, но в том формате в котором она хранится в оперативе (т.е. 4 байта).

Код:

type
  massiv=array[0..3] of byte; // тип массива для хранения
  DW2MAS = ^massiv;

procedure TForm1.Button1Click(Sender: TObject);
var
mas:massiv; // наш массив
d:dword; // наша Dword переменная
begin
d:=$12345678;
mas:=DW2MAS(@d)^;
//теперь содержимое массива будет таким: $78,$56,$34,$12
end;

такимже образом можно окнвертировать и другие типы. Главное чтобы из размер был одинаков. т.е. Dword - некогда не засунуть в array[0..1] of byte;
Кстати, такимже образом можно и наоборот. засовывать массив из 4-х байт в dword
Этот метод хорошь тем что работа идет напрямую с память, без использования каких либо дополнительный вычислений.
-----------------
При работе с IP адресами многие видели, что они храняться в озу в прямом порядку, т.е. старший байт на старшем месте. т.е. IP - 127.0.0.1 бедет храниться 7F000001
Это очень не удобно для увелицения значения IP адреса. т.е. к примеру появилась необходимость пройтись по диапазону 192.168.2.1 - 192.168.2.128. Сложность заключается в том что при увеличении значения на 1 будет увеличиваться старшая часть IP адреса, а не младшая (как это нам нужно).
Для этих целей пожно использовать простой метод основанный на инструкции МП - bswap которая меняет порядок байт.
Код:

function incIP(d:dword):dword;assembler;
asm
bswap eax // поменять поряд байт
inc eax // увеличить на 1
bswap eax // поменять обратно
end;

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
var
ca:sockaddr_in;
d:dword;
begin
d:=inet_addr('127.0.0.1'); // сохраним IP адресс
d:=incIP(d); // увеличим на 1
d:=incIP(d); // увеличим на 1
d:=incIP(d); // увеличим на 1
ca.sin_addr.s_addr:=d; // запишем в структуру.
end;

Тем самым в ca.sin_addr.s_addr будет число которое будет соотвествовать IP - 127.0.0.4

sni4ok 14.05.2007 12:21

Цитата:

Сообщение от _Great_
Вот нашел несколько полезных советов для M$ Visual Studio.

7. Отладочные значения в различных областях памяти программы

более подробно тут
_http://www.codeguru.com/Cpp/W-P/win32/tutorials/article.php/c9535/

gevara 14.05.2007 21:49

Ещё не понимаю код типа:
d=inet_addr('127.0.0.1');
здесь логичней присваивать значение напрямую: d=0x0100007F;
хотя, это не так наглядно, но ведь можно
d=0x0100007F; // 127.0.0.1
тоже самое с инициализацией портов, юникод строк:
#define InitUnicodeString(string) {sizeof(string)-2,sizeof(string),string}

slesh 14.05.2007 22:59

2 gevara Ну это я просто для наглядности юзал функцию винсоковскую.
Суть была не в том как записать IP адрес, а в том, как увеличить его :)

_Great_ 14.05.2007 23:43

Цитата:

Сообщение от gevara
_Great_
Вообще для бряка я создаю макрос
#define __INT3 __asm int 3;
более наглядней.

Удобно при написании дров использовать Int 3 причём с опкодом CC, а не с CD 03. тем более что некоторые ядерные отладчики имеют функцию: заменить все int3 (0xCC) на nop (0x90). НО ,как я понимаю, в VC такой возможности нет. обидно.

Вообще-то, __asm int 3 геренит CC, а не CD 03.
Команда CD 03 отнюдь не аналогична CC и таких "отладочных" свойств, насколько я помню, не имеет.
CC - Это НЕ просто однобайтовая замена для CD 03.
Поэтому __asm int 3 генерит сразу CC, а чтобы сгенерить CD 03 надо явно написать
__asm emit 0xCD
__asm emit 0x03

2all - постирал несколько постов, заканчиваем офтопить

Joker-jar 20.05.2007 15:16

Delphi.

Функция округления числа до нужного количества знаков:
Код:

function RoundFloat(R: Extended; Decimals: Integer): Extended;
var
  Factor: Extended;
begin
  Factor := Int(Exp(Decimals * Ln(10)));
  Result := Round(Factor * R) / Factor;
end;

Используя вышеописанную функцию, получаем окгугленный размер файла в килобайтах (наиболее универсальная величина для большинства файлов):
Код:

Function FileSizeInKb(YourFile : String) : string;
Var
  arg: extended;
  F : Integer;
Begin
  F:=FileOpen(YourFile,0);
  arg := FileSeek(F,0,2);
  FileClose(F);
  arg:=roundfloat(arg/1024,1);
  result:=floattostr(arg);
End;

Функция проверяет, открыт ли порт на хосте, с указанием времени ожидания ответа. Отличная вещь для написания сканера одного порта на диапазоне адресов. Зависимость - winsock2, обертку под делфню можно найти хде угодно
Код:

function PingPort(host: string; portnum: word; tim: integer): boolean;
var
  k: integer;
  s, opt: Integer;
  FSocket: TSOCKET;
  busy : boolean;
  addr : TSockAddr;
  hEvent : THandle;
  fset : TFDset;
  tv : TTimeval;
  tec :PServEnt;
  PName:String;
  GInitData : TWSADATA;
begin
  result := false;
  WSAStartup(MAKEWORD(2,0), GInitData);
  addr.sin_family := AF_INET;
  addr.sin_addr.s_addr := INADDR_ANY;
  addr.sin_port := htons(portnum);
  hEvent := WSACreateEvent();
  busy:=false;
  FSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  WSAEventSelect(FSocket, hEvent, FD_WRITE + FD_CONNECT);
  addr.sin_addr := LookupName(host);
  connect(FSocket, @addr, sizeof(addr));
  if WSAGetLastError()=WSAEINPROGRESS then
    begin
      closesocket (FSocket);
      busy:=true;
    end;
  FD_Zero(fset);
  if busy <> true then
    FD_SET (FSocket, fset);
  tv.tv_sec := tim;
  tv.tv_usec := 0;
  s:=select (1, nil, @fset, nil, @tv);
  if busy then
    exit;
  if FD_ISSET (FSocket, fset) then
    begin
      s:=Sizeof(Opt);
      opt:=1;
      getsockopt(FSocket, SOL_SOCKET, SO_ERROR, @opt, s);
      if opt=0 then
        result := true;
      closesocket(FSocket);
    end;
  WSACloseEvent(hEvent);
  WSACleanup;
end;

Шустрый метод копирования файлов. При правильной подборке размера буфера можно добиться космической скорости :)
Код:

procedure CopyFile(file1,file2: string);
var
  FromF, ToF: file;
  NumRead, NumWritten: Integer;
  Buf: array[1..2048] of Char;
begin
  AssignFile(FromF, file1);
  Reset(FromF, 1);
  AssignFile(ToF, File2);
  Rewrite(ToF, 1);
    repeat
      BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
      BlockWrite(ToF, Buf, NumRead, NumWritten);
    until
      (NumRead = 0) or (NumWritten <> NumRead);
  CloseFile(FromF);
  CloseFile(ToF);
end;


_Great_ 20.05.2007 15:38

>>Шустрый метод копирования файлов. При правильной подборке размера буфера можно добиться космической скорости

вообщето апишка есть для этого

Joker-jar 24.05.2007 12:49

Delphi. Простая, но очень полезная функция (при написании игр, искусственных интеллектов, эмуляторов игровых автоматов и т.д.). Функция идентична random: boolean, только с параметром percent, (0 <= percent <= 100) - вероятностью истинного результата. Например, probrandom(80) вернет true с вероятностью 80%.
Код:

function probrandom(percent: integer): boolean;
begin
  result := random(100) < percent;
end;

З.Ы. Не забываем инициализировать генератор случайных чисел (randomize)

Joker-jar 31.05.2007 22:16

Код:

const
  alf = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

  function power(x,y: integer): int64;
  begin
    if x = 0 then
      result := 0
    else
      result := trunc(exp(ln(x)*y));
  end;

  function fromdec(d: int64; s: integer): string;
  begin
    if (d < s) then
      result := alf[d + 1]
    else
      result := fromdec(d div s,s) + alf[d mod s + 1];
  end;

  function todec(d: string; s: integer): int64;
  begin
    if length(d) = 1 then
      result := pos(d,alf) - 1
    else
      result := (pos(d[1],alf) - 1) * power(s, length(d)-1) + todec(copy(d,2,length(d)-1),s);
  end;

Delphi. Системы счисления. 2 <= s <= 36

З.Ы. Рекурсия рулит

_Great_ 31.05.2007 23:40

И все-таки, как написано в 1 посте, "Не стоит превращать тему в свалку исходников, выбирайте наиболее интересные и полезные участки кода."
Выбирайте действительно ИНТЕРЕСНЫЙ и НЕОБЫЧНЫЙ код, какието нестандартные приемы там и прочее. Банальщина типа реализации CopyFile не очень нужна.

Ch3ck 22.06.2007 03:36

Выводит содержимое файла в шестнадцатиричном формате и в виде ASCII кодов.

Код:

#include <iostream>
#include <fstream>
#include <cctype>
#include <iomanip>
using namespase std;

int main(int argc, char *argv[])
{
                if(!argc=2) {
                  cout << "USAGE: Display"
                  rerutn 1;
  }
ifstream in(argv[1], ios::in | ios::binary);
                if(!in) {
                cout << "Cannot open input file.\n";
                return 1;
  }
register int i, j;
int count = 0;
char c[16];
                cout.setf(ios::uppercase);
                        while(!in.eof()){
                        for(i=0; i<16 && !in.eof(); i++) {
                          in.get(c[i]);
  }
if(i<16) i--;
for(j=0; j<i; j++)
cout << setw(3) << hex << (int) c[j];
for(; j<16; j++) cout << "  ";
cout << "\t";
for(j=0; j<i; j++)
if(isprint(c[j])) cout << c[j];
else cout << ".";
cout endl;
          count++;
if(count=16) {
count=0;
cout << "Press ENTER to continue: "'
cin.get();
cout << endl;
}
}
in.close();
return 0;
}


ZaCo 23.06.2007 19:15

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

[53x]Shadow 23.06.2007 19:56

Функция-шаблон считывания из потока n байт.
Написал специально для удобства работы с различными потоками в stl. Так, например, нет стандартного метода считывания n байт из объекта ifstream в string в stl.


Код:

template
        <
                typename InputIterator,
                typename OutputIterator
        >
        void readn(InputIterator begin, InputIterator end, int n, OutputIterator out)
        {
                for(;n > 0 && begin != end;--n, ++begin, ++out)
                {
                        *out = *begin;
                }
        }


ZaCo 24.06.2007 14:29

Будь-то программирование на winapi, будь-то программирование на posix при создании многопоточного приложения одинаково часто возникает неудобство выраженное в виде невозможности стандартным образом передать своей функции через CreateThread/pthread_create более одного аргумента. Пример двух используемых функций по вин thread.c:
Код:

/*
 thread.c by ZaCo
*/

#include <windows.h>
//вспомогательная функция-поток из которой вызываем запрашиваемую функцию

void * Thread(int * temp)
 {
  void * func=(void *)(*temp);//вызываемая функция
  temp++;                    //переходим к следующему адресу
  int num=*(int *)temp;      //кол-во аргументов

  int i;

  temp+=num;                //сдвигаемся просто до конца тк аргументы нужно передавать задом-наперед ;)

  for(i=num-1;i>=0;i--,temp--)
  {
    int * param=*(int **)temp;//каждый раз получаем нужный адрес
    _asm push param;
  }

  delete [2+num] (temp-1);    //освобождаем память выделенную в NewThread

  _asm call func;            //вызываем функцию
  return NULL;
 }

//функция создания потока: func - функция, num - кол-во аргументов-указателей после num

void * NewThread(void * func, unsigned int num, ...)
 {
  int * temp=new int[2+num];  //temp - массив адресов которые  в итоге нужно передать функции-потоку
  memcpy(temp,&func,(2+num)*sizeof(void*));

  CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,temp,0,NULL));
 }

//
Работа в основной программе:
Код:

#include <stdio.h>
void * NewThread(void *, unsigned int, ...);
void * Thread(int *);
#include "thread.c"

void * func(int * a,char * b,int * c, char * s)
 {
  printf("%d+%d+%d+%s\n",*a,*b,*c,s);
  return NULL;
 }

int main(int argc, char* argv[])
{
 int a=5,b=7,g=4;
 char s[]="it's xek!";

 NewThread(func,4,&a,&b,&g,&s[0]);

 Sleep(1000);
 return 0;
}


_Great_ 27.06.2007 15:15

Для Microsoft Visual Studio 7 (она же 2003 .NET):

Если нет желания таскать за собой рантайм в том или ином виде, а при его отключении линкер орёт на неразрешенные ссылки на __chkstk, ___securitycookie и @__security_check_cookie@4, можно обойтись следующей реализацией этого (писал сам :))

Код:

// будем тока выделять место в стеке под переменные
extern "C" __declspec(naked) void _chkstk()
{
        __asm
        {
                // Enter: EAX = size

                xor ebx, ebx
                xchg [esp], ebx  // запоминаем адрес возврата
                add esp, 4  // удаляем его
                sub esp, eax  //  выделяем место
                push ebx  // кладем адрес возврата на место и возвращаемся
                retn
        }
}

// любое число, в принципе, но чтобы оно было "случайное", а не вида 00010000.
// хороший вариант - 19237845 или BACBBAFD или что-нибудь в этом роде
extern "C" DWORD_PTR __security_cookie = 0x5F8E34B0;

// проверка на переполнение буфера
extern "C" void _fastcall __security_check_cookie(DWORD_PTR cookie)
{
        if(__security_cookie != cookie)  // можно добавить ченить более умное при ошибке
                __asm int 3;
}


[53x]Shadow 15.08.2007 11:58

Stl/c++
 
Преобразование из string в int с контролем целостности ;)

Код:

bool to_number(char const* beg, int sz, int& num)
        {
                char* end = 0;
                int tmp_num = ::strtol(beg, &end, 10);
                if(end != beg + sz)
                {
                        return false;
                }
                num = tmp_num;
                return true;
        }

use:
Код:

std::string value;
int num;
if (!to_number(value.c_str(), value.size(), num))
        return false;


Piflit 07.09.2007 01:00

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

gevara 21.10.2007 23:07

Возникла у меня такая идейка. Функции в Си могут возвращать значение в регистрах eax, edx. Иными словами можно заставить функцию возвратить 2 значения вместо того, чтобы не передавать лишний укказатель указатель. Может быть это не совсем корректно, зато иногда бывает удобно.

насколько я разобрался - здесь можно поступить двумя способами:

LARGE_INTEGER function xx()
{
}

void main()
{
LARGE_INTEGER a;
a = xx();
a.HigthPart ..
a.LowPart
}

или непосредственно к регистрам
void main()
{
int a,b;
xx();
__asm{mov b,edx}
__asm{mov a,eax}
}

P.S. для более удобново вызова можно попробовать переопределить операторы...

Joker-jar 29.10.2007 20:04

Генерации кодов Грея. Пишу для тех, кто знает о чем я. Короче, как вы помните, чувак предложил рекурсивный алгоритм и все такое. Я чуть не попутал, когда убедился, что ту же самую последовательность можно сгенерировать практически одной строкой:

Код:

for i := 0 to N-1 do
  writeln(i xor (i div 2));

Какая нах рекурсия!!!

Пример использования. Генерация всех подмножеств множества:

Код:

{$apptype console}

var
  U: array[0..3] of byte = (1, 2, 3, 4);
  i,k: integer;

function checkbit(d, i: integer): boolean;
begin
  if (d and (1 shl i)) = 0 then
    result := false
  else
    result := true;
end;

begin
  writeln('Dano: { 1 2 3 4 }'#13#10);
  for i := 0 to  16 - 1 {16 - 2^N, N=4 - мощность множества} do
    begin
      write('{ ');
      for k := 4-1 {N-1} downto 0 do
        if checkbit((i xor (i div 2)), k) then
          write(U[4-1 {N-1} -k],' ');
      writeln('}');
    end;
  readln;
end.

Также хочу показать простой способ построения таблиц истиности логических выражений. Допустим, нужно построить:
Код:

X or (Y and Z)
| X | Y | Z | Y and Z | X or (Y and Z) |
| 0 | 0 | 0 |    0    |        0      |
| 0 | 0 | 1 |    0    |        0      |
| 0 | 1 | 0 |    0    |        0      |
| 0 | 1 | 1 |    1    |        1      |
| 1 | 0 | 0 |    0    |        1      |
| 1 | 0 | 1 |    0    |        1      |
| 1 | 1 | 0 |    0    |        1      |
| 1 | 1 | 1 |    1    |        1      |

Вот так это делается быстро и красиво:

Код:

{$apptype console}

type
  myBool = 0..1;

var
  X,Y,Z: myBool;
  i: integer;

function checkbit(d, i: integer): myBool;
begin
  if (d and (1 shl i)) = 0 then
    result := 0
  else
    result := 1;
end;

begin
  writeln('X or (Y and Z)');
  writeln('| X | Y | Z | Y and Z | X or (Y and Z) |');
  for i := 0 to 7 do
    begin
      X := checkbit(i,2);
      Y := checkbit(i,1);
      Z := checkbit(i,0);
      write('| ',X,' | ',Y,' | ',Z,' |    ',Y and Z,'    |        ',X or (Y and Z),'      |');
      writeln;
    end;
  readln;
end.


slesh 02.11.2007 00:35

Вот только недавно сталкнулся с одной проблемой в сетевом программировании.
Навреное и другие тоже сталкивались с этим.
А именно: когда стоит на компе Kaspersky Antivirus ( на 6 версии - 100%) то
любой connect будет удачным. В том смысле:
при коннекте к любому компу на заведомо закрытый порт - коннект пройдет удачно, в следствии того, что каспер подменяет IP и порт на localhost:1110 - какбы на свой прокси, с целью проверки трафика и именно по этой причине все коннекты являются удачными. Следовательно необходимо заботится о том, чтобы какимнить обрабом проверять естьли коннект реально или нет!

DWORD 02.11.2007 00:53

Цитата:

Сообщение от gevara
Возникла у меня такая идейка.

Ну и извращение! Си позволяет возвращать не только простые, но и сложные типы данных, например структуры, только зачем это нужно, мне например вообще почти никогда не бывает нужно. В С++ - да. При перегрузке операций для классов там без этого не обойтись, а в си...

__asm{mov b,edx} вот это вообще издевателсьво. Остерегайтесь ассемблерных вставок в windows программах пользователського режима - они там ненужны, кроме того такой С-код непереносим. В gcc специально сделали синтаксис АТ&Т, чтобы неповадно было ассемблер использовать :)

DWORD 02.11.2007 00:56

Цитата:

Сообщение от slesh
чтобы какимнить обрабом проверять естьли коннект реально или нет!

С такой проблемой не сталкивался, но выход напрашивается, если ты используешь sockets api, проверяй после установки соединения, с кем реально ты соединился (если не sockets api, то наверняка тоже можно)

slesh 02.11.2007 01:17

2 DWORD
В том то и дело, что по всем параметрам соединение идет какбы нормальное. потмоу что всё подменяется довольно четко. А писать громозкий код для определения сетевой активности своей проги - тоже както не хочется.
Если сам разрабатываешь и серверную и клиентскую часть, то выход прост. А если к примеру делается клиент к уже существующему серверу и идет жесткая организация пакетов типа по RFC то тогда возникает проблема. К примеру у меня тесты показали, что даже даже первые данных посланные через send удачно посылаются, даже если сервер недоступен. Просто данные шлются касперу, а от него теряются. Хотя повторная отправка пакета - уже выдает ошибку отправки, при отключеном сервере.

ZaCo 02.11.2007 02:41

2slesh очень странно, в принципе, чисто теоретически, подобный перехват со стороны касперского должен официально подделывать возвращаемые ip-пакеты (адрес отправителя) иначе бы возникли проблемы с работой многих сетевых приложений. насчет connect'а: я так понимаю, что касперский должен выполнять функцию шлюза локальной сети, однако если тут этого не происходит, то видимо он вообще работает с пакетами на высоком уровне))
если так, то лучше избавиться от подобного ПО:)
при определенных навыках можешь поработать с сырыми пакетами и посмотреть кто-что посылает. по-хорошему касперский должен быть ТОЧНО ip-прокси.

KEZ 02.11.2007 06:46

Касперский не перестаёт нас удивлять. А что же дальше? Инжект во все процессы, с целью посмотреть, что они будут делать? Заражение .ехе файлов на диске с целью закрепить свою защиту в системе?

_Great_ 02.11.2007 10:00

Цитата:

Остерегайтесь ассемблерных вставок в windows программах пользователського режима - они там ненужны, кроме того такой С-код непереносим. В gcc специально сделали синтаксис АТ&Т, чтобы неповадно было ассемблер использовать
Бред. Что куда неперносимо? В пределах разных Windows? С какой радости. Между платформами? Дык виндоус-код и так непереносим в этом смысле..
Так что уточни, что ты имел в виду.

ZaCo 02.11.2007 11:15

>>Бред. Что куда неперносимо?

>>программах пользователського режима - они там ненужны, кроме того такой С-код непереносим

с опущенным словом windows очень даже правильно:) про пользовательский режим - ну в общем-то правда, хотя наверняка найдутся примеры чья оптимизированная реализации на ассемблере будет нужна по части глупости компилятора. а C-код и правда не переносим будет, ведь асм-вставки это не стандарт языка.


Время: 01:58