Advertisement
Guest User

Untitled

a guest
Sep 16th, 2010
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.03 KB | None | 0 0
  1. /*
  2.   Example of myproxocket.dll by Luigi Auriemma
  3.  
  4.   if you don't know it, myproxocket.dll is a dll read by proxocket (ws2_32.dll/wsock32.dll)
  5.   and used to control some functions like send, recv, connect and so on.
  6.   all you need to do is just creating a myproxocket.dll file exporting the CDECL functions
  7.   explained below
  8.  
  9.   The following are all the available functions under your control:
  10.  
  11.   myfunction <- original functions     execution BEFORE or AFTER the original functions and return value
  12.   ------------------------------------------------------------------------------------------------------
  13.   mysocket   <- socket, WSASocket      BEFORE  >= 0: returns your value: INVALID_SOCKET: returns INVALID_SOCKET, any_other_value: calls the original function
  14.   myconnect  <- connect, WSAConnect    BEFORE  0: calls real connect, SOCKET_ERROR: returns SOCKET_ERROR, any_other_value: bypasses the real connect and returns 0
  15.   myaccept   <- accept, WSAAccept      AFTER   the main program will receive the same return value returned by you
  16.   mybind     <- bind                   BEFORE  0: calls real bind, SOCKET_ERROR: returns SOCKET_ERROR, any_other_value: bypasses the real bind and returns 0
  17.   myclose    <- closesocket            AFTER   the main program will receive the same return value returned by you
  18.   myrecv     <- recv, WSARecv          AFTER   the main program will receive the same return value returned by you
  19.   myrecvfrom <- recvfrom, WSARecvFrom  AFTER   the main program will receive the same return value returned by you
  20.   mysend     <- send, WSASend          BEFORE  >= 0: calls real send, SOCKET_ERROR: returns SOCKET_ERROR, any_other_value: bypasses the real send/WSASend and returns the original len
  21.   mysendto   <- sendto, WSASendTo      BEFORE  >= 0: calls real sendto, SOCKET_ERROR: returns SOCKET_ERROR, any_other_value: bypasses the real sendto/WSASendTo and returns the original len
  22.  
  23.   in the AFTER functions remember that, obviously, they are called only if the original function succeded
  24.   so if the real recv() returned SOCKET_ERROR myrecv() will be NOT called.
  25.   note: in case you are asking what is the value of SOCKET_ERROR/INVALID_SOCKET it's -1
  26.  
  27.   as visible in this code, all the my* functions have the same prototype of the original homonym functions
  28.   (except mysend and mysendto due to technical reasons) so there are no possibilities of errors or
  29.   misunderstandings.
  30.  
  31.   for example, in myrecv and myrecvfrom the len value is the one returned by recv/recvfrom and buf
  32.   contains the data received, while in myaccept the s value is the socket returned by accept().
  33.   so, if the original recv failed (connection lost) myrecv will be NOT called.
  34.  
  35.   in mysend, instead, you can control the content and length of the data before the real sending, and the
  36.   return value will be used as length for the original function, if you return a value which is not
  37.   SOCKET_ERROR and is minor than 0 (for example -0x77777777) the original send() will be NOT called
  38.   allowing you to drop a packet or to generate a socket error visible by the main program.
  39.  
  40.   use the following instructions for retrieving IP and port from a sockaddr structure:
  41.     u32     ip   = 0;
  42.     u16     port = 0;
  43.     if(name) {
  44.         ip   = ((struct sockaddr_in *)name)->sin_addr.s_addr;
  45.         port = ntohs(((struct sockaddr_in *)name)->sin_port);
  46.     }
  47.  
  48.   remember that you SHOULD delete ALL the my* functions that you don't use, so if you need only to modify
  49.   the incoming UDP packets you can remove mysocket, myconnect, mybind, myaccept and all the other functions
  50.   except myrecvfrom (even DllMain can be removed).
  51.  
  52.   as visible, in this example there are already various real socket functions which can be used in any
  53.   moment without losing time to implement them: socket connect, accept, bind, close, recv, recvfrom, send
  54.   and sendto.
  55.  
  56.   at the moment this plugin must be considered experimental so any feedback about improving it is highly
  57.   welcome and needed.
  58.  
  59.   gcc -o myproxocket.dll myproxocket.c -shared
  60. */
  61.  
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <winsock.h>
  66. #include <windows.h>
  67.  
  68. u_int str2ip(u_char *data) {
  69.     unsigned    a, b, c, d;
  70.  
  71.     if(!data[0]) return(0);
  72.     sscanf(data, "%u.%u.%u.%u", &a, &b, &c, &d);
  73.     return((a & 0xff) | ((b & 0xff) << 8) | ((c & 0xff) << 16) | ((d & 0xff) << 24));
  74. }
  75.  
  76. u_char *ip2str(u_int ip) {
  77.     static u_char  data[16];
  78.  
  79.     sprintf(data, "%hhu.%hhu.%hhu.%hhu",
  80.         (ip & 0xff), ((ip >> 8) & 0xff), ((ip >> 16) & 0xff), ((ip >> 24) & 0xff));
  81.     return(data);
  82. }
  83.  
  84. u_short net16(u_short num) {
  85.     int         endian = 1; // big endian
  86.  
  87.     if(!*(char *)&endian) return(num);
  88.     return((num << 8) | (num >> 8));
  89. }
  90.  
  91. u_int net32(u_int num) {
  92.     int         endian = 1; // big endian
  93.  
  94.     if(!*(char *)&endian) return(num);
  95.     return(((num & 0xff000000) >> 24) |
  96.            ((num & 0x00ff0000) >>  8) |
  97.            ((num & 0x0000ff00) <<  8) |
  98.            ((num & 0x000000ff) << 24));
  99. }
  100.  
  101. #define htons       net16
  102. #define ntohs       net16
  103. #define htonl       net32
  104. #define ntohl       net32
  105. #define inet_ntoa   ip2str
  106. #define inet_addr   str2ip
  107.  
  108. /* code which adds Winsock support to your hook, so you can use the original functions everytime you want! */
  109. /* it's not (easily) possible to link the winsock functions directly in this dll otherwise will be loaded the */
  110. /* bridge functions of proxocket (ws2_32.dll is in the same folder) */
  111.  
  112. static HMODULE wsock = NULL;
  113. static WINAPI SOCKET (*real_socket)(int af, int type, int protocol) = NULL;
  114. static WINAPI int (*real_connect)(SOCKET s, const struct sockaddr *name, int namelen) = NULL;
  115. static WINAPI SOCKET (*real_accept)(SOCKET s, const struct sockaddr *name, int *namelen) = NULL;
  116. static WINAPI int (*real_bind)(SOCKET s, const struct sockaddr *name, int namelen) = NULL;
  117. static WINAPI int (*real_close)(SOCKET s) = NULL;
  118. static WINAPI int (*real_recv)(SOCKET s, char *buf, int len, int flags) = NULL;
  119. static WINAPI int (*real_recvfrom)(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) = NULL;
  120. static WINAPI int (*real_send)(SOCKET s, char *buf, int len, int flags) = NULL;
  121. static WINAPI int (*real_sendto)(SOCKET s, char *tbuf, int len, int flags, const struct sockaddr *to, int tolen) = NULL;
  122.  
  123. void init_myproxocket(void) {   // in this example I use this function for loading the real sockets function in case we want to use them
  124.     char    winpath[MAX_PATH];
  125.  
  126.     if(wsock) return;   // already set
  127.  
  128.     GetSystemDirectory(winpath, sizeof(winpath));
  129.     strcat(winpath, "\\ws2_32.dll");
  130.  
  131.     wsock = LoadLibrary(winpath);
  132.     if(!wsock) return;
  133.  
  134.     real_socket    = (void *)GetProcAddress(wsock, "socket");
  135.     real_connect   = (void *)GetProcAddress(wsock, "connect");
  136.     real_accept    = (void *)GetProcAddress(wsock, "accept");
  137.     real_bind      = (void *)GetProcAddress(wsock, "bind");
  138.     real_close     = (void *)GetProcAddress(wsock, "close");
  139.     real_recv      = (void *)GetProcAddress(wsock, "recv");
  140.     real_recvfrom  = (void *)GetProcAddress(wsock, "recvfrom");
  141.     real_send      = (void *)GetProcAddress(wsock, "send");
  142.     real_sendto    = (void *)GetProcAddress(wsock, "sendto");
  143. }
  144.  
  145. void free_myproxocket(void) {
  146.     if(wsock) {
  147.         FreeLibrary(wsock);
  148.         wsock = NULL;
  149.     }
  150. }
  151.  
  152.     // this function can be used also to know only if a string exists or not, it's enough to use NULL instead of new like in the example in myrecv
  153. u_char *find_replace_string(u_char *buf, int *len, u_char *old, u_char *new) {
  154.     int     i,
  155.             tlen,
  156.             oldlen,
  157.             newlen,
  158.             found;
  159.     u_char  *nbuf,
  160.             *p;
  161.  
  162.     found  = 0;
  163.     oldlen = strlen(old);
  164.     tlen   = *len - oldlen;
  165.  
  166.     for(i = 0; i <= tlen; i++) {
  167.         if(!strnicmp(buf + i, old, oldlen)) found++;
  168.     }
  169.     if(!found) return(buf); // nothing to change: return buf or a positive value
  170.  
  171.     if(!new) return(NULL);  // if we want to know only if the searched string has been found, we will get NULL if YES and buf if NOT!!!
  172.     newlen = strlen(new);
  173.  
  174.     if(newlen <= oldlen) {  // if the length of new string is equal/minor than the old one don't waste space for another buffer
  175.         nbuf = buf;
  176.     } else {                // allocate the new size
  177.         nbuf = malloc(*len + ((newlen - oldlen) * found));
  178.     }
  179.  
  180.     p = nbuf;
  181.     for(i = 0; i <= tlen;) {
  182.         if(!strnicmp(buf + i, old, oldlen)) {
  183.             memcpy(p, new, newlen);
  184.             p += newlen;
  185.             i += oldlen;
  186.         } else {
  187.             *p++ = buf[i];
  188.             i++;
  189.         }
  190.     }
  191.     while(i < *len) {
  192.         *p++ = buf[i];
  193.         i++;
  194.     }
  195.     *len = p - nbuf;
  196.     return(nbuf);
  197. }
  198.  
  199. /*
  200. SOCKET __cdecl mysocket(int af, int type, int protocol) {
  201.     // example: convert a TCP connection in a TCP packets-oriented stream... I guess doesn't work
  202.     if(type == SOCK_STREAM) {
  203.         return(real_socket(af, SOCK_DGRAM, protocol));
  204.     }
  205.  
  206.     // example: convert a TCP connection in an UDP connection, indeed also UDP can be handled with connect, send and recv
  207.     if(protocol == IPPROTO_TCP) {
  208.         return(real_socket(af, type, IPPROTO_UDP));
  209.     }
  210.  
  211.     // example: if the family is AF_INET we return an error which is received by the main program
  212.     if(af == AF_INET) {
  213.         return(INVALID_SOCKET);
  214.     }
  215.  
  216.     // call the real socket/WSASocket
  217.     return(-0x77777777); // negative and different than INVALID_SOCKET
  218. }
  219. */
  220.  
  221. /*
  222. int __cdecl myconnect(SOCKET s, const struct sockaddr *name, int namelen) {
  223.    
  224.     // example: avoid the connection to host 1.2.3.4
  225.     if(((struct sockaddr_in *)name)->sin_addr.s_addr == inet_addr("208.167.249.27")) {
  226.         return(SOCKET_ERROR);
  227.     }
  228.        
  229.     // example: avoid the connection to any port 1234
  230.     if(ntohs(((struct sockaddr_in *)name)->sin_port) == 1234) {
  231.         return(SOCKET_ERROR);
  232.     }
  233.        
  234.     // example: redirect any connection from host 1.2.3.4 to host 192.168.0.2
  235.     if(((struct sockaddr_in *)name)->sin_addr.s_addr == inet_addr("208.167.249.26")) {
  236.         ((struct sockaddr_in *)name)->sin_addr.s_addr = inet_addr("208.167.249.27");
  237.     }
  238.    
  239.     return(0);
  240. }
  241. */
  242.  
  243. /*
  244. SOCKET __cdecl myaccept(SOCKET s, const struct sockaddr *name, int *namelen) {
  245.     // at the moment this function can't be really used to avoid connections from a specific host
  246.     // but if we want to avoid connection from 1.2.3.4 we can "try" the following although it's not very good
  247.     if(((struct sockaddr_in *)name)->sin_addr.s_addr == inet_addr("1.2.3.4")) {
  248.         return(0);  // don't return SOCKET_ERROR or the main program could decide to exit/quit
  249.     }
  250.     return(s);
  251. }
  252. */
  253.  
  254. int __cdecl mybind(SOCKET s, const struct sockaddr *name, int namelen) {
  255.     /*
  256.     // example: avoid the binding of interface 192.168.0.1, the main program could quit
  257.     if(((struct sockaddr_in *)name)->sin_addr.s_addr == inet_addr("208.167.249.27")) {
  258.         return(SOCKET_ERROR);
  259.     }
  260.     */
  261.  
  262.     /*
  263.     // example: avoid the binding of port 1234, the main program could quit
  264.     if(ntohs(((struct sockaddr_in *)name)->sin_port) == 2302) {
  265.         return(SOCKET_ERROR);
  266.     }
  267.     */
  268.    
  269.    
  270.     // example: substituite the binding of interface 192.168.0.1 with 10.10.10.10
  271.     if(((struct sockaddr_in *)name)->sin_addr.s_addr == inet_addr("127.0.0.1")) {
  272.         ((struct sockaddr_in *)name)->sin_addr.s_addr = inet_addr("208.167.249.27");
  273.     }
  274.    
  275.    
  276.     // example: as above but uses 127.0.0.1 instead of 0.0.0.0 (INADDR_ANY) so the main program can be used only locally
  277.     //if(((struct sockaddr_in *)name)->sin_addr.s_addr == htonl(INADDR_ANY)) {
  278.     //    ((struct sockaddr_in *)name)->sin_addr.s_addr = inet_addr("208.167.249.27");
  279.     //}
  280.     return(0);
  281. }
  282.  
  283. /*
  284. int __cdecl myclose(SOCKET s) {
  285.     // example: this function has only for your internal use
  286.     // for example if you need to track all the sockets and you need to know when they are closed to free memory or remove an entry
  287.     return(0);
  288. }
  289. */
  290.  
  291. /*
  292. int __cdecl myrecv(SOCKET s, u_char *buf, int len, int flags) {
  293.     // example: if buf contains the word "hello" return a socket error (the main program will close the socket or will exit)
  294.     if(!find_replace_string(buf, &len, "hello", NULL)) {
  295.         return(SOCKET_ERROR);
  296.     }
  297.  
  298.     // example: fill all the bytes of buf with 'A's
  299.     memset(buf, 'A', len);
  300.  
  301.     // example: return 1 byte less than the bytes we have received (like returning 99 instead of 100)
  302.     if(len > 1) len--;
  303.  
  304.     // remember that a value <= 0 is usually considered an error by the main program when handles TCP streams
  305.     // while for any other packet (UDP, ICMP and so on) it can be 0 without problems
  306.     return(len);
  307. }
  308. */
  309.  
  310. /*
  311. int __cdecl myrecvfrom(SOCKET s, u_char *buf, int len, int flags, struct sockaddr *from, int *fromlen) {
  312.     // examples: watch the examples of myrecv
  313.  
  314.     // example: drop any packet from the host 1.2.3.4
  315.     if(((struct sockaddr_in *)from)->sin_addr.s_addr == inet_addr("1.2.3.4")) {
  316.         return(SOCKET_ERROR);
  317.     }
  318.  
  319.     return(len);
  320. }
  321. */
  322.  
  323. /*
  324. int __cdecl mysend(SOCKET s, u_char **retbuf, int len, int flags) {
  325.     u_char  *buf = *retbuf; // do NOT touch this
  326.  
  327.     // if you have allocated a new buffer it will be AUTOMATICALLY freed by proxocket so
  328.     // remember only to NOT return a const/static buffer which cannot be freed!
  329.  
  330.     // example: send a packet of 10000 'A's if the one we want to send contains the "hello" bytes
  331.     if(!find_replace_string(buf, &len, "hello", NULL)) {
  332.         buf = malloc(10000);
  333.         memset(buf, 'A', 10000);
  334.         return(10000);
  335.     }
  336.  
  337.     // replace any occurrency of "hello" with that new string
  338.     buf = find_replace_string(buf, &len, "hello", "don't tell me goodbye send()");
  339.  
  340.     // send the following message before the one in which we are: real_send and then this send
  341.     char message[] = "yes, I can use send() in any moment!";
  342.     real_send(s, message, strlen(message), flags);
  343.  
  344.     // do not execute this send
  345.     return(-0x77777777);
  346.  
  347.     *retbuf = buf;  // do NOT touch this
  348.     // return >= 0 for calling the real send
  349.     // return SOCKET_ERROR avoids the sending of the data but returns SOCKET_ERROR to the main program, use it to generate a socket error
  350.     // return any other value to skip the send function
  351.     return(len);
  352. }
  353. */
  354.  
  355. /*
  356. int __cdecl mysendto(SOCKET s, u_char **retbuf, int len, int flags, const struct sockaddr *to, int tolen) {
  357.     u_char  *buf = *retbuf; // do NOT touch this
  358.  
  359.     // if you have allocated a new buffer it will be AUTOMATICALLY freed by proxocket so
  360.     // remember only to NOT return a const/static buffer which cannot be freed!
  361.  
  362.     // example: send a packet of 10000 'A's if the one we want to send contains the "hello" bytes
  363.     if(!find_replace_string(buf, &len, "hello", NULL)) {
  364.         buf = malloc(10000);
  365.         memset(buf, 'A', 10000);
  366.         return(10000);
  367.     }
  368.  
  369.     // replace any occurrency of "hello" with that new string
  370.     buf = find_replace_string(buf, &len, "hello", "don't tell me goodbye sendto()");
  371.  
  372.     // send the following message before the one in which we are: real_sendto and then this sendto
  373.     char message[] = "yes, I can use sendto() in any moment!";
  374.     real_sendto(s, message, strlen(message), flags, to, tolen);
  375.  
  376.     // do not execute this sendto
  377.     return(-0x77777777);    // negative and different than SOCKET_ERROR
  378.  
  379.     *retbuf = buf;  // do NOT touch this
  380.     // return >= 0 for calling the real sendto
  381.     // return SOCKET_ERROR avoids the sending of the data but returns SOCKET_ERROR to the main program, use it to generate a socket error
  382.     // return any other value to skip the sendto function
  383.     return(len);
  384. }
  385. */
  386.  
  387. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
  388.     switch(fdwReason) {
  389.         case DLL_PROCESS_ATTACH: {
  390.             DisableThreadLibraryCalls(hinstDLL);
  391.             init_myproxocket(); // put your init here
  392.             break;
  393.         }
  394.         case DLL_PROCESS_DETACH: {
  395.             free_myproxocket(); // put anything to free here
  396.             break;
  397.         }
  398.         default: break;
  399.     }
  400.     return(TRUE);
  401. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement