подмена выдачи

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Sharky, 30 May 2009.

  1. Sharky

    Sharky Elder - Старейшина

    Joined:
    1 May 2006
    Messages:
    487
    Likes Received:
    312
    Reputations:
    46
    собственно понадобилось выполнить такую задачу ... чтоб при заходе человека на страницу полученный от сервера результат перехватывался и заменялся на тот который я укажу ...
    понимаю что надо написать подобие сниффера который эти пакеты будет перехватывать..но опыта не хватает

    подскажите что почитать ... желательно на c++ или delphi ...
     
  2. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    1) Delphi - забудь. Максимум что ты можешь сделать - это написать DLL котоаря будет внедряться в проги(или насильно внедрить в брайзер) и будет хукать функцию recv и тому подобные. и в ней уже подменять данные.
    2) Если С++ то дров который будет фильтровать на уровне TDI устройство \device\tcp
     
  3. Sharky

    Sharky Elder - Старейшина

    Joined:
    1 May 2006
    Messages:
    487
    Likes Received:
    312
    Reputations:
    46
    а примеры или доки подкинуть можешь?
     
  4. Gar|k

    Gar|k Moderator

    Joined:
    20 Mar 2009
    Messages:
    1,166
    Likes Received:
    266
    Reputations:
    82
    Я думаю для поставленной задачи подойдет и RAW сокет в "promiscuous_mode".

    Пример кода на Си
    Code:
    int main(int argc, char * argv[]) {
    
        WSADATA wsadata;
        SOCKET sock;
        CHAR szHostName[16];
        HOSTENT * phe;
        SOCKADDR_IN sa;
        DWORD flag = TRUE;
    
        unsigned char buffer[65555];
    
        struct in_addr need; // А это необходимо для inet_ntoa макроса
    
        WSAStartup(MAKEWORD(2, 2), &wsadata);
    
        sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    
        if (sock == INVALID_SOCKET) {
            printf("Error create socket\n");
            return 0;
        }
    
        if (gethostname(szHostName, sizeof szHostName) != 0) {
            printf("Error get hostname\n");
            return 0;
        }
    
        phe = gethostbyname(szHostName);
        if (phe == NULL) {
            printf("Error get hostname data\n");
            return 0;
        }
    
        ZeroMemory( & sa, sizeof sa);
        sa.sin_family = AF_INET;
        sa.sin_addr.s_addr = ((struct in_addr * ) phe - >h_addr_list[0]) - >s_addr;
    
        need.s_addr = sa.sin_addr.s_addr;
    
        if (bind(sock, &sa, sizeof(sa)) != 0) {
            printf("Error set bind socket\n");
            return 0;
        }
    
        if (ioctlsocket(sock, SIO_RCVALL, &flag) == SOCKET_ERROR) {
            printf("Error activate promiscuous mode\n");
            return 0;
        }
    
        while (1)
    
        {
            resbuf = recvfrom(sock, buffer, sizeof buffer, 0, 0, 0);
    
            // ставим фильтр тока на исходящий траффик
            // можешь убрать или настроить только на входящий
            ip = (struct my_ip * )(buffer);
            if (need.s_addr != ip - >ip_source) {
                continue;
            }
    
            // анализ принятого буффера
        }
    
        closesocket(sock);
        WSACleanup;
    
        return 0;
    }
    
    Практически тоже самое на MASM
    Code:
    .386
    .model flat, stdcall
    option casemap:none
    
    include C:\masm32\include\windows.inc
    
    include C:\masm32\include\masm32.inc ;много полезных функций masm32
    includelib C:\masm32\lib\masm32.lib
    
    include C:\masm32\include\kernel32.inc
    includelib C:\masm32\lib\kernel32.lib
    
    include C:\masm32\include\user32.inc ;функции user32.dll
    includelib C:\masm32\lib\user32.lib
    
    include C:\masm32\include\ws2_32.inc ;работ с сокетами - winsock
    includelib C:\masm32\lib\ws2_32.lib
    
    
          
    BUFFER_SIZE equ 50000 ;буфер, который будем использовать для загрузки страницы - 50000 байт
    
    
    SIO_RCVALL equ 98000001h
    
    .data?
    sock SOCKET ?
    buffer db BUFFER_SIZE dup(?)
    hfile DWORD ?
    szHostName db 16 dup(?)
    
    .data
    WSAStruct WSADATA <> ;структура, которая нужна для инициализации сокета
    SocketAddress sockaddr_in <> ;структура, содержащая адрес и порт, куда будем подключаться
    
    
    fname db "C:\small\test.log",0
    
    
    flag DWORD TRUE  
    
    ;--------------
    Caption db "Сообщение",0
    SockErr1 db "Ошибка инициализации сокета",0
    Gethosterr db "Ошибка получении имени хоста",0
    GetHostFail db "Ошибка получения IP-адреса. Проверьте наличие сетевого подключения.",0
    BindErr db "Error set bind socket",0
    ioErr db "Error activate promiscuous mode",0
    ;--------------
    
    
    
    
    .code
    start:
    
    	invoke WSAStartup,0101h,offset WSAStruct ;инициализируем сокет версии 2.2 (0101h)
    	cmp eax,0
    	je @F
          		invoke MessageBox,NULL,offset SockErr1,offset Caption,MB_ICONERROR
          		jmp qApp
    
    @@: ; создаем сокет
    	invoke socket,AF_INET,SOCK_RAW,IPPROTO_IP 
    	cmp eax,INVALID_SOCKET
       	jne @F
          		invoke MessageBox,NULL,offset SockErr1,offset Caption,MB_ICONERROR
          		jmp exitAppQsocks
    
    @@: ; получаем имя хоста
       
    	mov sock,eax 
    	
    	invoke gethostname,offset szHostName,16
    	cmp eax,0
    	je @F
    		invoke MessageBox,NULL,offset Gethosterr,offset Caption,MB_ICONERROR
    		jmp closesock
    
    @@: ;получаем IP-адрес хоста
            invoke gethostbyname,offset szHostName 
            cmp eax,0
            jne @F
            	invoke MessageBox,NULL,offset GetHostFail,offset Caption,MB_ICONERROR ;если не удалось - выведем ошибку и выйдем из программы
    		jmp closesock
    
    @@:
     
            mov eax,[eax+12] ;эти три строчки - получение ip-адреса из возвращаемой gethostbyname структуры
            mov eax,[eax]
            mov eax,[eax] ;в итоге IP-адрес в виде double будет в регистре eax
     
     	mov SocketAddress.sin_family, AF_INET
            mov SocketAddress.sin_addr,EAX 
    
    @@: ;биндим сокет
    
    	invoke bind,sock,offset SocketAddress, SIZEOF SocketAddress
    	cmp eax,0
    	je @F
            	invoke MessageBox,NULL,offset BindErr,offset Caption,MB_ICONERROR ;если не удалось - выведем ошибку и выйдем из программы
    		jmp closesock
    
    @@: ; переводим в нужный режим
    
    	invoke ioctlsocket, sock, SIO_RCVALL, offset flag
    	cmp eax,SOCKET_ERROR
    	jne @F
      		invoke MessageBox,NULL,offset ioErr,offset Caption,MB_ICONERROR ;если не удалось - выведем ошибку и выйдем из программы
    		jmp closesock
    
    @@:
    
    
    while_1: ;бесконечный цикел
    
    invoke recvfrom,sock,offset buffer,BUFFER_SIZE,0,0,0
    
    
    
    
    @@:
    ; тут надо чето делать :)
    
    invoke CreateFile,offset fname,GENERIC_WRITE,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 ;создаем файл, если существует, то перезаписываем его (флаг OPEN_ALWAYS)
    cmp eax,-1
    jne @F
       invoke MessageBox,NULL,offset ioErr,offset Caption,MB_ICONERROR ;если не удалось - выведем ошибку и выйдем из программы
    		jmp closesock
    
    @@:
    mov hfile,eax
     invoke WriteFile,hfile,offset buffer,BUFFER_SIZE,0,0 ;запишем данные в файл
     invoke CloseHandle,hfile ;и закроем его
    
    jmp while_1
    
    
    closesock:
    invoke closesocket,sock
    
    exitAppQsocks:
    call WSACleanup 
    
    qApp :
    invoke ExitProcess,0
    
    end start
    
    За тобой анализ буффера в памяти :)
    лично я для Си версии использовал юниксовую функцию memmem

    Code:
    #if defined(__cplusplus) && __cplusplus
     extern "C" {
    #endif
    
    void *memmem(const void *buf, const void *pattern, size_t buflen, size_t len)
    {
    
    #if defined(__TURBOC__) && (__TURBOC__ >= 0x500)
    
          char *bf = (char *)buf, *pt = (char *)pattern, *p = bf;
    
          while (len <= (buflen - (p - bf)))
          {
                if (NULL != (p = memchr(p, (int)(*pt), buflen - (p - bf))))
                {
                      if (0 == memcmp(p, pattern, len))
                            return p;
                      else  ++p;
                }
                else  break;
          }
          return NULL;
    
    #else /* Borland/Turbo C/C++ version prior to 4.x */
    
          size_t i, j;
          char *bf = (char *)buf, *pt = (char *)pattern;
    
          if (len > buflen)
                return (void *)NULL;
    
          for (i = 0; i <= (buflen - len); ++i)
          {
                for (j = 0; j < len; ++j)
                {
                      if (pt[j] != bf[i + j])
                            break;
                }
                if (j == len)
                      return (bf + i);
          }
          return NULL;
    
    #endif
    }
    
    #if defined(__cplusplus) && __cplusplus
     }
    #endif
    
     
    _________________________
    1 person likes this.
  5. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 Gar|k
    1) ПОДМЕНА ВЫДАЧИ, а не снифанье. твоим куском ты сможешь тока отснифать пришедший пакет
    2) слишком паливно когда висит еще один процес который это делает
    3) твой код только на один адаптер. По хорошему нужно перечислить все IP которыми обладает комп и запустить отдельный поток для снифанья c каждого ip

    2 Sharky Примеры - в инете поищи доку по формграберу какомунить.
    А вообще я гдето с пол года назад для интереса писал на Delphi DLL которая аттачилась ко всем GUI процессам, хукала там
    'wininet.dll', 'InternetReadFile' - IE так работает
    'wsock32.dll', 'recv'
    'ws2_32.dll', 'recv'
    'ws2_32.dll', 'WSARecv' - Opera

    Прожка анализировала входящие данные и подменяла номера WM кошельков.
    Точно не помню как уже тема называлась.
     
  6. Gar|k

    Gar|k Moderator

    Joined:
    20 Mar 2009
    Messages:
    1,166
    Likes Received:
    266
    Reputations:
    82
    2 Slesh
    ну а замечания дельные, ТС стоит их учесть :)

    да, действительно, о ПОДМЕНЕ ВЫДАЧИ я чет и не подумал...

    меня всегда интересовало, а можно ли похитить сокет другой программы? вроде бы у Криса Касперски я читал что-то подобное..
     
    _________________________
  7. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    вообще это чуть по другому действует.
    Ты должен найти нужный тебе дискриптор сокета а потом скопировать его в свою программу через DuplicateHandle(...);
    И у себя уже будешь юзать как угодно. Но если ты считаешь данные то настоящая прога уже их не получит.
     
  8. Gar|k

    Gar|k Moderator

    Joined:
    20 Mar 2009
    Messages:
    1,166
    Likes Received:
    266
    Reputations:
    82
    Дааа я сделал это!!! 6:11 (надо бы спать пойти)
    переписал вот эту ересь http://slow.alfamoon.com/content/uploads/list_socket.dpr
    на Си в VS2008 не имея либ DDK и доков по ntdll.dll ... все искал в нете

    Итак внимание програмулина ищет и показывает все открытые сокеты в системе путем чтения Hendle запущеных процессов... естественно можно заюзат Tool Help и переписать ее под конкретный процесс...

    Нафиг это надо? Можно спокойно перехватить любой сокет любого запущего процесса!!! влась!!! мухаха (*нервно дергается глаз*)

    извините за "некрасивый код" мне просто надо было заставить его работать!

    Code:
    // list_socket.cpp: определяет точку входа для консольного приложения.
    //
    
    #include "stdafx.h"
    
    #include <windows.h>
    #include <winternl.h>
    #include <Ntstatus.h>
    #include <Winsock.h>
    
    
    #pragma comment(lib, "ws2_32.lib")
    
    #define SystemHandleInformation 16
    #define BUF_SIZE 102400
    
    typedef enum _POOL_TYPE
    {
             NonPagedPool = 0,
             PagedPool = 1,
             NonPagedPoolMustSucceed = 2,
             DontUseThisType = 3,
             NonPagedPoolCacheAligned = 4,
             PagedPoolCacheAligned = 5,
             NonPagedPoolCacheAlignedMustS = 6,
             MaxPoolType = 7,
             NonPagedPoolSession = 32,
             PagedPoolSession = 33,
             NonPagedPoolMustSucceedSession = 34,
             DontUseThisTypeSession = 35,
             NonPagedPoolCacheAlignedSession = 36,
             PagedPoolCacheAlignedSession = 37,
             NonPagedPoolCacheAlignedMustSSession = 38
    } POOL_TYPE;
    
    typedef struct _OBJECT_NAME_INFORMATION {
    
    
      UNICODE_STRING          Name;
      WCHAR                   NameBuffer[0];
    
    } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
    
    typedef struct _OBJECT_TYPE_INFORMATION {
    
    
    
      UNICODE_STRING          TypeName;
      ULONG                   TotalNumberOfHandles;
      ULONG                   TotalNumberOfObjects;
      WCHAR                   Unused1[8];
      ULONG                   HighWaterNumberOfHandles;
      ULONG                   HighWaterNumberOfObjects;
      WCHAR                   Unused2[8];
      ACCESS_MASK             InvalidAttributes;
      GENERIC_MAPPING         GenericMapping;
      ACCESS_MASK             ValidAttributes;
      BOOLEAN                 SecurityRequired;
      BOOLEAN                 MaintainHandleCount;
      USHORT                  MaintainTypeList;
      POOL_TYPE               PoolType;
      ULONG                   DefaultPagedPoolCharge;
      ULONG                   DefaultNonPagedPoolCharge;
    
    
    
    } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
    
    typedef enum _OBJECT_INFORMATION_CLASS {
        ObjectBasicInformation,
        ObjectNameInformation,
        ObjectTypeInformation,
        ObjectAllInformation,
        ObjectDataInformation
    } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
    
    
    typedef NTSTATUS (CALLBACK *LPFNZwQuerySystemInformation)(
      SYSTEM_INFORMATION_CLASS SystemInformationClass,
      PVOID SystemInformation,
      ULONG SystemInformationLength,
      PULONG ReturnLength
    );
    
    typedef NTSTATUS (CALLBACK *LPFNNtQueryObject)(
      HANDLE               ObjectHandle,
      OBJECT_INFORMATION_CLASS ObjectInformationClass,
      PVOID               ObjectInformation,
      ULONG                Length,
      PULONG              ResultLength );
    
    typedef NTSTATUS (CALLBACK *LPFNZwClose)(HANDLE  Handle);
    
    LPFNZwQuerySystemInformation ZwQuerySystemInformation;
    LPFNNtQueryObject NtQueryObject;
    LPFNZwClose ZwClose;
    
    
    
    
    typedef struct _SYSTEM_HANDLE_INFORMATION {
      USHORT ProcessId;
      USHORT CreatorBackTraceIndex;
      UCHAR ObjectTypeNumber;
      UCHAR Flags;
      USHORT Handle;
      PVOID Object;
      ACCESS_MASK GrantedAccess;
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    
    typedef struct _SYSTEM_HANDLE_INFORMATION_EX {
    
      ULONG NumberOfHandles;
      SYSTEM_HANDLE_INFORMATION Information[1];
      
    } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
    
    
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    DWORD  PID,ret;
    NTSTATUS  ss;
    int i, j, ress, rem_port, loc_port;
    PUNICODE_STRING us;
    POBJECT_TYPE_INFORMATION ot;
    char *remaddr,*locaddr;
    
    sockaddr_in sockname, locname;
    WSAData   WSData;
    LPVOID   pinfo, codeadr;
    DWORD    tid, wsa_error;
    
    HINSTANCE hNTdll = LoadLibrary(L"Ntdll.dll"); 
    HANDLE    hProcess, hcp, ObjHandle, hh;
    if(!hNTdll) return 1;
    
    ZwQuerySystemInformation = (LPFNZwQuerySystemInformation) 
    GetProcAddress(hNTdll, "ZwQuerySystemInformation");
    
    NtQueryObject=(LPFNNtQueryObject) 
    GetProcAddress(hNTdll, "NtQueryObject");
    
    ZwClose=(LPFNZwClose) 
    GetProcAddress(hNTdll, "ZwClose");
    
     WSAStartup(0x202, &WSData);
      printf("There are the following sockets opened on system:\n");
    
     // Get the number of handles on the system
      DWORD buffer_size = 0;
      SYSTEM_HANDLE_INFORMATION_EX temp_info;
    
    
      NTSTATUS status = ZwQuerySystemInformation(
          (SYSTEM_INFORMATION_CLASS)SystemHandleInformation, &temp_info, 
          sizeof(temp_info), &buffer_size);
    
    
      SYSTEM_HANDLE_INFORMATION_EX *system_handles =
        (SYSTEM_HANDLE_INFORMATION_EX*)(new BYTE[buffer_size]);
    
    
      status = ZwQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation,
                                        system_handles,
                                        buffer_size, &buffer_size);
    
      ot=(POBJECT_TYPE_INFORMATION)malloc(BUF_SIZE);
      us=(PUNICODE_STRING)malloc(BUF_SIZE);
    
    
      //printf("nb of handles = %d", system_handles->NumberOfHandles);
    for(i=0;i<system_handles->NumberOfHandles;i++)
    {
    	 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, system_handles->Information[i].ProcessId);
    	 if (hProcess != INVALID_HANDLE_VALUE){
              hh=(HANDLE)system_handles->Information[i].Handle;
    		 if(DuplicateHandle(hProcess,hh,
                           INVALID_HANDLE_VALUE, &ObjHandle, DUPLICATE_SAME_ACCESS, 0, 0))
    		 {
    			ss = NtQueryObject(ObjHandle,
                              ObjectTypeInformation, ot, BUF_SIZE, &ret);
    
    			if (ss == STATUS_SUCCESS)
    			{
    				if(lstrcmp(ot->TypeName.Buffer,L"File")==0){
    					ss=NtQueryObject(ObjHandle,ObjectNameInformation, us, BUF_SIZE, &ret);
    					
    					
    
    					if(ss==STATUS_SUCCESS){
    						if(lstrcmp(us->Buffer,L"\\Device\\Afd")==0)
    						{
    							
    							
    
    							 ress = sizeof(sockaddr_in);//--- commenting this line would cause an 10014 error.
    							getpeername((SOCKET)ObjHandle, (sockaddr *)&sockname, &ress);
    
    							//--- determine local ip and port
    							ress = sizeof(sockaddr_in);//--- commenting this line would cause an 10014 error.
    							getsockname((SOCKET)ObjHandle, (sockaddr *)&locname, &ress);
    				
    
    
    							//--- type conversion
    							remaddr = inet_ntoa(sockname.sin_addr);
    							rem_port = ntohs(sockname.sin_port);
    
    							locaddr = inet_ntoa(locname.sin_addr);
    							loc_port = ntohs(locname.sin_port);
    
    							
    							wprintf(L"PID=%d; Local=%S:%d; Peer=%S:%d\n",system_handles->Information[i].ProcessId,locaddr,loc_port,remaddr,rem_port);
    					
    
    						}
    					}
    				}
    
    			
    			//ZwClose(ObjHandle); //--- we don't need this handle any more
    			}
    
    
    		 }
    
    
    		 CloseHandle(hProcess);
    	 }
    
    }
    
    
    free(us);
    free(ot);
       WSACleanup();
    
    FreeLibrary(hNTdll);
    
    getchar();
    
    return 0;
    }
    
    
    
     
    _________________________
    2 people like this.
  9. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    А мог бы и не замарачиваться с динамическим импортом из ntdll а просто скачать ntdll.lib и уже юзать статический импорт. Кода было бы меньше )
    А вообще тема не про то. Код оформи и можешь кинуть в мини стать по кодингу. Там пригодится код. Потому что по аналогии можно захватить не только сокет, но и файл.
     
  10. Gar|k

    Gar|k Moderator

    Joined:
    20 Mar 2009
    Messages:
    1,166
    Likes Received:
    266
    Reputations:
    82
    оформил выложил ) читайте
    http://forum.antichat.ru/threadnav69514-3-10.html
     
    _________________________
    #10 Gar|k, 31 May 2009
    Last edited: 31 May 2009
  11. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    если влом писать супер-пупер троян то можно поступить так - подправить файл hosts чтобы он перенаправлял на скрипт в инете, который бы и собирал/выдавал нужную инфу
     
    #11 bons, 31 May 2009
    Last edited: 31 May 2009
  12. Sharky

    Sharky Elder - Старейшина

    Joined:
    1 May 2006
    Messages:
    487
    Likes Received:
    312
    Reputations:
    46
    думал об этом...и реализуется просто...но потом решил что надо изменять только часть страницы
     
  13. login999

    login999 Elder - Старейшина

    Joined:
    12 Jun 2008
    Messages:
    491
    Likes Received:
    280
    Reputations:
    92
    Я не плаваю в теме - но у мну такой вопрос - а нельзя ли сделать немного по-другому - сделать Duplicate Handler, создать свой Хэнделр и передать его браузеру - потом читать из оригинального сокета и передававть браузеру через скормленный ему хэндлер уже модифицированное т.е. сделать прокладку между сокетом и браузером,
     
  14. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    1) тебе придется постоянно забирать десткрипторы браузера.
    2) Ты не сможешь навязать браузеру свой сокет.

    Твоя реализация будет пахать только в том случае если ты будеш хукать функцию socket из винсок чтобы сразу отлавливать сокеты и подменять. но это еще больше всё усложнит
     
  15. Artorios

    Artorios New Member

    Joined:
    23 Feb 2012
    Messages:
    15
    Likes Received:
    0
    Reputations:
    0
    Я вообще не вижу смысл юзать duplicateHandle,так как,например,данные отправятся браузерному сокету,а твоя прога за браузерный сокет всё прочтёт,а сам браузер нет,что тогда получится???.Поэтому поводу в книге Вильямса "Системное программирование" написано.
    Кстати, Slesh,интересно было бы та твою реализацию обработчика Recv/WsaRecv посмотреть,хотя бы одним глазком)