‏הצגת רשומות עם תוויות windows 7. הצג את כל הרשומות
‏הצגת רשומות עם תוויות windows 7. הצג את כל הרשומות

יום שישי, 22 בפברואר 2013

Proxy Server Guide



הרבה ארגונים אינם מאפשרים כניסה לאתרים מסויימים בשעות העבודה, שלא נדבר על ארגונים מאובטחים שאינם רוצים שמידע חסוי יצא החוצה, אחד הכלים שמאפשרים לנו לנתח תעבורה הם Proxies שמהווים נקודת מעבר למידע שעובר ברשת, לדוגמה ארגון שמנצל את ה Proxy על מנת לעקוב אחרי אנשים בארגון, או Proxy שמזהה פרסומות בדפי אינטרנט ומוריד אותם, מסנן אתרי פורנו וכו'.



קיימים 2 סוגים של Proxies:
  • Forward Proxies - מקבל בקשות ומעביר לאינטרנט.
  • Reverse Proxies - מקבל בקשות מהאינטרנט ומעביר לשרת.
בתחום אבטחת המידע ה Proxy מנצח גם בתחום ההתקפה וגם בתחום ההגנה, בעזרת Proxy ניתן לטשטש את העקבות בכך שנסתיר את הכתובת שלנו בעזרת הכתובת של ה Proxy (ראה Anonymous Proxy) ,  אבל גם מאפשר לנו לעקוב אחרי הבקשות ולסנן בקשות זדוניות כמו Sql Injection / Cross Side Scripting.

יאללה לקוד!

שימו לב! התוכנית עובדת על Sockets בלבד ולא תומכת ב  (Secure Socket Layer (SSL.

נקודת המוצא עבור התוכנית שהיא צריכה קודם כל להאזין לאיזה Port בעזרת אובייקט מסוג TcpListener השלב הבא הוא לתפוס את החבילה לנתח ולהעביר אותה ליעד, אומנם זה נשמע פשוט אבל כמו תמיד העסק נהפך למסובך יותר כאשר מספר חבילות מגיעות ביחד לדוגמה דף אינטרנט יכול להכיל בתוכו מספר קישורים משרתים שונים שזמני התגובה שלהם שונים לכן עלינו לייצר מחסנית שתכיל בתוכה את כל החיבורים ותנהל אותם וכמובן לעטוף כל חיבור עם Thread על מנת שנוכל לעבוד במקביל.

ProxyHandler.cs

המחלקה שמנהלת את החיבור של המשתמש לשרת המבוקש, בתוכה יש Socket שמייצג את המשתמש ו Thread שמריץ את הפונקציה ()handle שמעבירה את הבקשה לשרת ומהשרת למשתמש, זו הפונקציה החשובה ביותר ובתוכה ניתן לערוך את הבקשות והתגובות מהשרתים והמשתמשים ולממש את הסוג הרצוי של ה Proxy, קיימות פונקציות נוספות במחלקה שתומכות בתהליך ועורכות את הבקשות.

במקרה שלנו ה Proxy מעביר בקשות ממשתמשים לשרתי אינטרנט ב Port 80, משנה את הבקשות המקוריות לבקשות של ה Proxy ומחזיר את התשובות למשתמשים.


//**** Proxytype.blogspot.com ****

using System;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.Net;

namespace Proxy
{
    public enum TaskStaus
    {
        STANDBY,
        ACTIVE,
        DONE
    }

    public class ProxyHandler
    {
       
        public TaskStaus _taskStatus = new TaskStaus();
        Thread _thread;
        Socket _socket;

        public ProxyHandler(Socket socket)
        {
            _socket = socket;
        }

        public void run()
        {
           _taskStatus = TaskStaus.ACTIVE;

           _thread = new Thread(new ThreadStart(handle));
           _thread.Start();
        }

        public void handle()
        {

            try
            {

                //set request buffer as the size of the socket buffer
                byte[] _clientRequestBuffer = new byte[_socket.ReceiveBufferSize];
                if (_socket.Receive(_clientRequestBuffer, 0, _clientRequestBuffer.Length, SocketFlags.None) != 0)
                {
                    string request = Encoding.ASCII.GetString(_clientRequestBuffer);

                    //start spliting the request to rows
                    string[] _lineArray = split_packet(request);

                    //checking if splitting success
                    if (_lineArray.Length == 0)
                    {
                        _taskStatus = TaskStaus.DONE;
                        _socket.Close();
                        return;
                    }

                    //geting host from first request line
                    string hosturl = get_hostname(_lineArray[0]);
                    //geting the requsted page
                    string page = get_page(_lineArray[0], hosturl);

                    //drop ssl
                    if (hosturl.Contains("443"))
                    {
                        _taskStatus = TaskStaus.DONE;
                        _socket.Close();
                        return;
                    }

                    //replace original page with edit page by proxy
                    _lineArray[0] = page;
                    request = rebuild_pkt(_lineArray);

                    //using DNS to get the ip of the host
                    IPHostEntry IPHost = Dns.GetHostEntry(hosturl);

                    //create the remote socket for the proxy connect with.
                    Socket remote_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    //make the connection on port 80
                    remote_socket.Connect(IPHost.AddressList[0], 80);

                    //sending the request
                    remote_socket.Send(ASCIIEncoding.ASCII.GetBytes(request));
                 
                    Console.WriteLine("SENDING REQUEST FROM:" + _socket.LocalEndPoint.ToString()+ " -TO-> " + ":" + hosturl);

                    //set response buffer as the size of the socket buffer
                    byte[] response = new byte[remote_socket.ReceiveBufferSize];

                    int bytesReceived = 1;

                    //check if connection is still alive after sending request
                    if (!remote_socket.Connected)
                    {
                        remote_socket.Close();
                       _socket.Close();
                        _taskStatus = TaskStaus.DONE;
                        return;
                    }

                    //set timeout for socket release socket faster
                    remote_socket.ReceiveTimeout = 2000;
                    _socket.SendTimeout = 2000;

                    //getting the first buffer of the response from the remote
                    bytesReceived = remote_socket.Receive(response, 0, response.Length, SocketFlags.None);

                    //running until end of response
                    while (bytesReceived > 0)
                    {
                        //release CPU time
                        Thread.Sleep(10);
                       
                        //sending packets from remote to the client
                        _socket.Send(response, bytesReceived, SocketFlags.None);
                       
                        //release CPU time
                        Thread.Sleep(10);

                        //reload the next buffer of the response
                        bytesReceived =remote_socket.Receive(response);

                        //release CPU time
                        Thread.Sleep(10);

                        Console.WriteLine("SENDING RESPONSE FROM:" + hosturl + " --TO--> " + _socket.RemoteEndPoint.ToString());
                       
                    }

                    //close response socket
                    remote_socket.Close();

                }

                //close the client socket
               _socket.Close();

                Thread.Sleep(100);

            }
            catch (Exception ex)
            {

                //close request socket
                _socket.Close();
            }
            finally
            {
                _socket.Close();
                _taskStatus = TaskStaus.DONE;
            }
      
        }


        /// <summary>
        /// return the host name from request
        /// removing unnecessary chars
        /// </summary>
        /// <param name="pkt_line">the first row in the request</param>
        /// <returns>host address</returns>
        private static string get_hostname(string pkt_line)
        {
            return pkt_line.Split(' ')[1].Replace("http://", "").Split('/')[0];
        }

        /// <summary>
        /// return the requested page from request
        /// fixing row as packet send from proxy
        /// remove the original hostname.
        /// </summary>
        /// <param name="pkt_line"></param>
        /// <param name="hostname"></param>
        /// <returns></returns>
        private string get_page(string pkt_line, string hostname)
        {
            return pkt_line.Replace("http://", "").Replace(hostname, "");
        }

        /// <summary>
        /// rebuild new request 
        /// </summary>
        /// <param name="_lines">edited request lines array</param>
        /// <returns>complete request string</returns>
        private static string rebuild_pkt(string[] _lines)
        {
            string _pkt = "";
            for (int i = 0; i < _lines.Length; i++)
            { _pkt = _pkt + _lines[i];}
            
            return _pkt;    
        }

       
        /// <summary>
        /// split the request to lines array
        /// </summary>
        /// <param name="pkt">complete request string</param>
        /// <returns>array of lines</returns>
        private string[] split_packet(string pkt)
        {
            string endLine = "\r\n";
            ArrayList _list = new ArrayList();

            string _line = "";
            for (int i = 0; i < pkt.Length; i++)
            {
                _line = _line + pkt[i];
                if (_line.EndsWith(endLine))
                {
                    _list.Add(_line);
                    _line = "";
                }
            }

            return (String[])_list.ToArray(typeof(string));
        }

        /// <summary>
        /// optinal write to log
        /// </summary>
        /// <param name="message">message to write</param>
        private  void writelog(string message)
        {
            FileStream _file = new FileStream(Environment.CurrentDirectory + "\\log.txt", FileMode.Append, FileAccess.Write);
            StreamWriter _writer = new StreamWriter(_file);
            _writer.WriteLine(message + "\n\r");
            _writer.Close();
            _file.Close();
            _writer.Dispose();
            _file.Dispose();

        }

    }
}

Program.cs

פונקציית Main מפעילה TcpListener של ה Proxy על פורט מסויים, ונכנסת ללואה אין סופית שה TcpListener מתחיל למלאות חיבורים במערך, לאחר מכן מופעלת הפונקציה ClearStack שמפעילה חיבורים ומנקה חיבורים שהושלמו.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using System.Net;
using System.Threading;

namespace Proxy
{
    class Program
    {
     
        static TcpListener _listener;
        static ArrayList _arr = new ArrayList();

        static void Main(string[] args)
        {
            //set the proxy port
            _listener = new TcpListener(IPAddress.Any, 8666);
            _listener.Start();

            //infinity loop
            while (true)
            {
                if (!_listener.Pending())
                {
                    clearStack();
                    continue;
                }
             
                Socket D = _listener.AcceptSocket();
                ProxyHandler _handler = new ProxyHandler(D);
                _arr.Add(_handler);
            }

        }

     

        /// <summary>
        /// stack of socket active the handle routine
        /// remove close handlers
        /// </summary>
        static void clearStack()
        {
            for (int i = _arr.Count - 1; i > 0; i--)
            {
                ProxyHandler _tmp = (ProxyHandler)_arr[i];

                switch (_tmp._taskStatus)
                {
                    case TaskStaus.STANDBY:
                       _tmp.run();
                        break;
                 
                    case TaskStaus.DONE:
                       _arr.Remove(_tmp);
                        break;
                    default:
                        break;
                }

                //release CPU time
                Thread.Sleep(10);
            }
        }

    }
}




סיכום:

אפשר להגיד ש Proxy הוא סוג של סוכן כפול לטוב ולרע והשימוש בו הוא על הגבול של חדירה לפרטיות מצד שני הוא מאפשר לשמור על תכנים ולסנן בקשות חשודות לכן השימוש בו משתנה מצורך לצורך, אבל מדובר באחד הכלים החשובים בעולם הרשתות.

תשתמשו בו בחוכמה!

יום שבת, 1 בדצמבר 2012

Process Network Analyzer .Net


דמיינו מצב שאתם מנהלים שרת אינטרנט וההייתם רוצים לדעת כמה משתמשים יש על השרת באותו רגע, וכמובן באיזה שירותים הם משתמשים, אחת הדרכים הנפוצות לעשות זו היא בעזרת שימוש בכלים קיימים ב Windows כמו ה Task Manager ו NetStat אבל זה תהליך מסורבל ומבלבל (נעבור עליו מיד) , חשבתי לעצמי איך ניתן לכתוב כלי כזה בעצמי ממקום להתחיל להתערבב עם הכלים ולזכור כל מיני מספרים...

השיטה הקלאסית:

נפעיל את חברנו הטוב - Task Manager.


חשוב לזכור שבהגדרות ה Default של טבלת ה Task Manager לא מופיעה העמודה של ה PID - Process Identifier שהיא חשובה לנו בהמשך, על מנת להפעיל את העמודה יש ללחוץ על View -> Select Columns ולסמן את ה CheckBox.


לאחר מכן נפתח Cmd ונרשום netstat -n -a -o ונקבל את רשימת החיבורים הפעילים שבמחשב ובנוסף ה PID של ה Process שאליו קשור החיבור.


עכשיו נקשר בין ה PID שמופיע ב NetStat לבין ה PID שמופיע ב Task Manager  ונדע כמה חיבורים יש לכל Process וכבר אפשר לראות שזה ממש לא נוח וצריכים כלי שיעשה זאת בשבילנו.

Process Analyzer

בסה"כ מדובר על כלי מאוד פשוט, קיימות מחלקות מוכנות ב .Net לניהול Processes שבעזרתם נקבל את רשימת ה Processes שרצים על המערכת, החלק היותר בעייתי איך מוצאים את כל החיבורים עבור כל Process, בעזרת Invoke (קריאה) ל פונקציות ומבנים ב Api נמצא את מה שאנחנו צריכים, אבל זה קצת טריקי, קיימת בעייה לגשת מתוכנית .Net שמוגדרת Managed Code לפונקציות API של Windows שמוגדרים כ UnManaged Code, אתר Pinvoke מכיל חתימות ידועות של פונקציות ב API של Windows שמאפשר לקרוא לפונקציה ישירות מ Net.

יש 2 פונקציות מרכזיות שאותן צריך להפעיל ב API של Windows הראשונה GetExtendedTcpTable והשנייה GetExtendedUdpTable, כל אחת מהפונקציות עובדת עם מבנים קבועים לצורך הדוגמה הפונקציה GetExtendedTcpTable צריכה לקבל מבנים מסוג MIB  שמיוחסים לפרוטוקול TCP כמו MIB_TCPROW_OWNER_PID MIB_TCPROW, MIB_TCPTABLE_OWNER_PID וכו',  בסיום הפונקציה מתמלא Buffer של טבלת החיבורים הפעילים וחוזר Pointer לאותו Buffer, מסביב כל פונקציה יש מעטפת שמכילה בתוכה את כל המבנים הדרושים.

tcpTavble.cs - מבוסס על הפונקציה שרשומה ב Pinvoke.

 public class tcpTable
    {
        //sort values by declaration order in memory
        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_TCPROW_OWNER_PID
        {
            public uint state;
            public uint localAddr;
            public byte localPort1;
            public byte localPort2;
            public byte localPort3;
            public byte localPort4;
            public uint remoteAddr;
            public byte remotePort1;
            public byte remotePort2;
            public byte remotePort3;
            public byte remotePort4;
            public int owningPid;
        }

        //sort values by declaration order in memory
        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_TCPROW
        {
            public uint dwState;
            public uint dwLocalAddr;
            public uint dwLocalPort;
            public uint dwRemoteAddr;
            public uint dwRemotePort;

        }

        //sort values by declartion order in memory
        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_TCPTABLE_OWNER_PID
        {
            public uint dwNumEntries;
            MIB_TCPROW_OWNER_PID table;
        }

        //sort values by declaration order in memory
        //enum of type for tcptable
        enum TCP_TABLE_CLASS
        {
            TCP_TABLE_BASIC_LISTENER,
            TCP_TABLE_BASIC_CONNECTIONS,
            TCP_TABLE_BASIC_ALL,
            TCP_TABLE_OWNER_PID_LISTENER,
            TCP_TABLE_OWNER_PID_CONNECTIONS,
            TCP_TABLE_OWNER_PID_ALL,
            TCP_TABLE_OWNER_MODULE_LISTENER,
            TCP_TABLE_OWNER_MODULE_CONNECTIONS,
            TCP_TABLE_OWNER_MODULE_ALL
        }

        //enum of the state of single row in the table
        public enum TCP_ROW_STATE
        {
            CLOSED,
            LISTEN,
            SENT,
            RCVD,
            ESTAB,
            FIN_WAIT1,
            FIN_WAIT2,
            CLOSE_WAIT,
            CLOSING,
            LAST_ACK,
            TIME_WAIT,
            DELETE_TCB
        }


        //expose signature, importing ip helper api
        [DllImport("iphlpapi.dll", SetLastError = true)]
        static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwOutBufLen, bool sort, int ipVersion, TCP_TABLE_CLASS tblClass, int reserved);

        //return the MIB_TCPROW_OWNER_PID array as connection 
        public MIB_TCPROW_OWNER_PID[] GetAllTcpConnections()
        {
            MIB_TCPROW_OWNER_PID[] tTable;
            int AF_INET = 2;    // IP_v4
            int buffSize = 0;

            // what the size of the memory we need to allocate for the table
            uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL, 0);
            //set pointer to buffer
            IntPtr buffTable = Marshal.AllocHGlobal(buffSize);

            try
            {
                //getting the buffer
                ret = GetExtendedTcpTable(buffTable, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL, 0);
                if (ret != 0)
                {
                    return null;
                }

                //convert pointer to MIB_TCPTABLE_OWNER_PID pointer
                MIB_TCPTABLE_OWNER_PID tab = (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(buffTable, typeof(MIB_TCPTABLE_OWNER_PID));
                IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));

                tTable = new MIB_TCPROW_OWNER_PID[tab.dwNumEntries];
 
                //reading the row from buffer using next position pointer
                //size of MIB_TCPROW_OWNER_PID
                for (int i = 0; i < tab.dwNumEntries; i++)
                {
                    //convert pointer to MIB_TCPROW_OWNER_PID pointer
                    MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
                    //save row in table
                    tTable[i] = tcpRow;
                    //go to the next entry.
                    rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));
                }

            }
            finally
            {
                // clear buffer
                Marshal.FreeHGlobal(buffTable);
            }

            return tTable;
        }
    }





הפונקציה GetExtendedUdpTable אומנם לא חשופה ב Pinvoke אבל היא מאוד דומה ל GetExtendedTcpTable.

udpTable.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace processNetwork
{
    public class udpTable
    {
        //sort values by declartion order in memory
        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_UDPROW_OWNER_PID
        {
            public uint LocalAddr;
            public byte localPort1;
            public byte localPort2;
            public byte localPort3;
            public byte localPort4;
            public int owningPid;
        }


        //sort values by declartion order in memory
        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_UDPTABLE_OWNER_PID
        {
            public uint dwNumEntries;
            MIB_UDPROW_OWNER_PID table;
        }



        enum UDP_TABLE_CLASS
        {
            UDP_TABLE_BASIC,
            UDP_TABLE_OWNER_PID,
            UDP_TABLE_OWNER_MODULE
        }

        //expose signature, importing ip helper api
        [DllImport("iphlpapi.dll", SetLastError = true)]
        static extern uint GetExtendedUdpTable(IntPtr pUddpTable, ref int dwOutBufLen, bool sort, int ipVersion, UDP_TABLE_CLASS tblClass, int reserved);

        //return the MIB_UDPROW_OWNER_PID array
        public MIB_UDPROW_OWNER_PID[] GetAllUdpConnections()
        {


            MIB_UDPROW_OWNER_PID[] tTable;
         
            int AF_INET = 2;    // IP_v4
            int buffSize = 0;


            // what the size of the memory we need to allocate for the table?
            uint ret = GetExtendedUdpTable(IntPtr.Zero, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID, 0);
            //set pointer to buffer
            IntPtr buffTable = Marshal.AllocHGlobal(buffSize);

            try
            {
                //getting the buffer
                ret = GetExtendedUdpTable(buffTable, ref buffSize, true, AF_INET, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID, 0);
                if (ret != 0)
                {
                    return null;
                }


                //convert pointer to MIB_UDPTABLE_OWNER_PID pointer
                MIB_UDPTABLE_OWNER_PID tab = (MIB_UDPTABLE_OWNER_PID)Marshal.PtrToStructure(buffTable, typeof(MIB_UDPTABLE_OWNER_PID));
             
                IntPtr rowPtr = (IntPtr)((long)buffTable + Marshal.SizeOf(tab.dwNumEntries));
         
                tTable = new MIB_UDPROW_OWNER_PID[tab.dwNumEntries];

                //reading the row from buffer using next position pointer
                //size of MIB_UDPROW_OWNER_PID     
                for (int i = 0; i < tab.dwNumEntries; i++)
                {
                    //convert pointer to MIB_UDPROW_OWNER_PID pointer
                    MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID)Marshal.PtrToStructure(rowPtr, typeof(MIB_UDPROW_OWNER_PID));
                    //save row in table
                    tTable[i] = udpRow;
                    //go to the next entry.
                    rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(udpRow));
                }

            }
            finally
            {
                // clear buffer
                Marshal.FreeHGlobal(buffTable);
            }

            return tTable;
        }
    }

}


הטבלה שחוזרת לנו מהפונקציה צריכה לעבור מספר המרות, יש להמיר Ip Number ל Ip Address, ולהוציא את ה Port מהאובייקט.

Utils.cs

 public static class utils
 {
        //convert uint to ip
        public static string convert_uint_to_ip(uint ipnum)
        {
            string ipAddress = new IPAddress(BitConverter.GetBytes(ipnum)).ToString();
            return ipAddress;
        }

        //convert bytes to ushort -> port
        public static ushort convert_bytes_to_port(byte p0, byte p1, byte p2, byte p3)
        {
            ushort port;
            byte[] arr = new byte[4];

            //check if the system is litte endian, or big endian and sort the array
            //reading the first 2 bytes
            if (BitConverter.IsLittleEndian)
            {
                arr[0] = p3;
                arr[1] = p2;
                arr[2] = p1;
                arr[3] = p0;
                port = BitConverter.ToUInt16(arr, 2);
            }
            else
            {
                arr[0] = p0;
                arr[1] = p1;
                arr[2] = p2;
                arr[3] = p3;
                port = BitConverter.ToUInt16(arr,0);
            }


            return port;


        }
    }



GUI




הפונקציה שהכי חשובה ב Gui היא init_processStack שאוספת את המידע ממחלקות ה Api שהצגתי וממחלקת ה Process הפנימית של .Net ומחברת בניהם על פי ה Process id ,שאר הפונקציות משמשות לעבודה מול הפקדים ב Gui לכן לא ארחיב עליהם. (פירוט מלא בקוד).

        /// collecting all the processes and the active connections
        private void init_processStack()
        {
            //create table of all the tcp connections
            tcpTable tcptbl = new tcpTable();
            tcpTable.MIB_TCPROW_OWNER_PID[] tcpRow = tcptbl.GetAllTcpConnections();

            //create table of all the udp connections
            udpTable udptbl = new udpTable();
            udpTable.MIB_UDPROW_OWNER_PID[] udpRow = udptbl.GetAllUdpConnections();

            //getting the processes from the machine
            Process[] pro = Process.GetProcesses();

            //add rows from tcp and udp tables inside sysProcess array
            //compate the process id inside the process array and the process id
            //inside the connections tables
            if (pro != null)
            {

                    prcs = new SysProcess[pro.Length];
          


                for (int i = 0; i < pro.Length; i++)
                {
                    prcs[i] = new SysProcess(pro[i]);

                    if (tcpRow != null)
                    {
                        for (int z = 0; z < tcpRow.Length; z++)
                        {
                            if (prcs[i].prc.Id == tcpRow[z].owningPid)
                                prcs[i].tcprows.Add(tcpRow[z]);
                        }
                    }

                    if (udpRow != null)
                    {
                        for (int z = 0; z < udpRow.Length; z++)
                        {
                            if (prcs[i].prc.Id == udpRow[z].owningPid)
                                prcs[i].udpRows.Add(udpRow[z]);
                        }
                    }

                }
            }

        }

סרט דוגמה:





קוד:
https://sourceforge.net/projects/processnetwork/

סיכום:

למדנו להכיר טוב יותר את התהליכים שרצים לנו על המחשב וכיצד ניתן לעקוב אחריהם, קיימים המון כלים בתחום , Mark Russinovich היה בין הראשונים שלקח את ניתוח המערכות של מיקרוספט לקצה וניתן למצוא המון ספרים שלו בתחום, בנוסף אני חייב להזכיר את הפרויקט Process Hacker שבקוד פתוח ב .Net שניתן ללמוד ממנו המון.

תתחילו לעקוב...


יום שבת, 18 בדצמבר 2010

File Upload With Flex And IIS 7

העברת קבצים ב Flash זה עניין מסובך שמצריך הכנות ובדיקות, התהליך מורכב מ 3 שלבים , השלב הראשון הוא ההגדרות של המערכת: IIS,הרשאות כתיבה בספריות ופתיחת פורטים השלב הבא הוא פיתוח האתר שאיתו ה Flex הולך לדבר, ושלב אחרון הוא פיתוח מנגנון העלאה ב Flex.

הגדרות מערכת
תחילה יש להגדיר את גודל המידע שיכול לעבור ואח"כ את גודל כל דרישה בשביל אותו מידע , ב IIS7  גודל המידע ה Default הוא  30 מגה ,אבל ניתן לדרוס את הפרמטר הזה בקובץ ApplicationHost שהוא בעצם קובץ XML שמכיל את הפרמטרים של ה IIS, בזמן טעינת האתר ה IIS טוען את הקובץ ולאחר מכן הוא טוען את ה Web.Config שמכילים את הפרמטרים של האתר העצמו.

ApplicationHost.config
תחילה נערוך את קובץ
C:\Windows\System32\inetsrv\config\applicationHost.config

נחפש את הבלוק שמגדיר את האתר שלנו ב ApplicationHost  (חשוב מאוד לגבות את הקובץ!) :

<location path="Your Website Name">
        <system.webserver>
           <security>
                        <requestfiltering>
                        <requestlimits maxallowedcontentlength="104857600">
                        </requestfiltering>
          </security>
          </system.webserver>
</location>
 
ברוב המצבים תגית האתר כבר מוגדרת ויש לוודא שקיימת גם תגית ה Security ואם לא להוסיף אותה.
ניתן לעשות את התהליך גם ב AppCmd שהיא אפליקצית Console שמגיע עם ה IIS 7 וניתן בעזרת לערוך את קובץ ה ApplicationHost ללא צורך לפתוח אותו , ובעצם למנוע תקלות בעקבות כתיבה לא נכונה.
 
C:\Windows\System32\inetsrv>appcmd set config "Your Website Name" -section:requestFiltering -requestLimits.maxAllowedContentLength:104857600 -commitpath:apphost
 
maxAllowedContentLength:104857600 מגדיר גודל של המידע שניתן להעביר, במקרה שלנו הגדלנו אותו ל 100 MB.
 
Web.config
נוסיף את הבלוק הבא בתוך התגית <system.web>(חשוב מאוד לגבות את הקובץ!) :
<httpRuntime executionTimeout="90" maxRequestLength="4096" />

maxRequestLength=2097151 הגדרנו את גודל של בקשה, בעצם 2 מגה.

Asp.net

האתר שלנו הוא מבוסס על Asp.net , המבנה שלו מאוד פשוט יש לנו ספרייה שמאחסנת לנו את הקבצים שנעלה לשרת, חשוב מאוד לתת לה הרשאות על מנת שנוכל לכתוב לספרייה, לצורך הדוגמה ניתן גישה ל Everyone.

יש לנו 2 קבצי Asp.net באתר ,הראשון הוא ה Upload Handler שתוכנת ה Flex שלנו מתחברת על מנת לשלוח את הקובץ לשרת, ודף נוסף שמציג לנו את ה Uploader עצמו.

upload_handler.aspx.cs

פונקציה אחת שבעצם שומרת לנו את הקבצים שאנו שולחים לספריית האחסון.

 protected void Page_Load(object sender, EventArgs e)
{
       string fileName = System.IO.Path.GetFileName(Request.Files[i].FileName);
       Request.Files[i].SaveAs(Server.MapPath("~/UploadedFiles/") + fileName);
upload_manager.aspx
דף שמכיל לנו את אובייקט ה Flesh  שמעלה קבצים.
חשוב מאוד להגדיר Cross Domain Policy , שנוכל להעלות מכל שרת, או מרשתות שמורשות לכך.

Flex

אפליקצית ה Flex מורכבת ממספר פונקציות:
פונקצית Start
זאת הפוקציה שמתחילה את התוכנה ומוסיפה מאיזינים (listeners) עבור אירועים בכפתורים.

פונקצית eventRespnse
פותחת לנו את ה File Dialog שנוכל לבחור קבצים.

פונקצית selectResponse
מחזירה לנו את כל הקבצים שנבחרו להעלאה.

פונקצית UploadFiles
הפונקציה ששולחת את הקובץ לשרת, תחילה היא קוראת לקובץ upload_handler ואח"כ מתחילה בשליחת הקובץ.

פונקצית uploadComplete
כשהעלאת הקובץ מסתיימת, עולה לנו אירוע שאומר שאפשר לשלוח את הקובץ הבא.

Gui
הממשק מורכב מ - Button,Labels,Progress Bar


סרטון הדגמה:


קוד להורדה:

בהצלחה...

יום רביעי, 6 באוקטובר 2010

Bios Commands Limits IIS 7

כונן שיתופי עבור מספר אתרי אינטרנט  הוא דבר חיוני במיוחד שמדובר בשילוב של שרתים עם מערכת Storage מרכזית , קיימים מספר אתרים שיושבים על אותו Storage ומספר שרתי אירוח (IIS) שונים שמפוזרים על שרתים נפרדים אבל שיש להם חיבור עם אותו Storage , כשיש יותר מידי קריאות ל Storage או קריאות ארוכות בסיביבת Asp.net , האתר יראה לנו את ההודעה הבאה:
 The network BIOS command limit has been reached
כלומר שלא ניתן ליצור קשר עם ה Storage כי עדיין יש קריאות שלא הסתיימו מולו.

תחילה נראה שהבעיה כנראה ב Storage אבל מסתבר שדווקא בשרתי ה IIS שמבוססים על WINDOWS 7 שבברירת מחדל שלהם חסרים 2 מפתחות חשובים ב Registry ולכן לא ניתן ליצור יותר חיבורים עם ה Storage.

 שני המפתחות החסרים:

MaxCmds - DWORD 32 BIT
MaxMpxct - DWORD 32 BIT

יש להוסיף את המפתחות האלה תחת המפתח:

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters


אבל עכשיו העניין איזה ערך להשים ב Value?? ובכן ה Default של 2 המפתחות הוא אמור להיות על 50, אבל אם צריך שתהיה אפשרות לבצע יותר קריאות ניתן להעלות אותו עד 65000 ב Decimal, אבל זה עלול לגרום למערכת לא להיות יציבה!! , עם אתם בעלי מערכת הפעלה 64 BIT אז אין בעיה להעלות אותו למקסימום אך עדיין זה לא מומלץ, הערך שאני השתמשתי הוא 800 כ HexDecimal או 2048 כ Decimal.

בהצלחה...

יום שלישי, 5 באוקטובר 2010

Multi Domain with default documents pointing to one website IIS 7

מסתבר שב IIS 7 יותר מסובך להגדיר Default Document לשני דומיינים שונים שמשתמשים באותו Web.config , ב IIS 6 האפשרות היתה יותר פשוטה , ה Default Document היה קשור ל Application Directory ולא היה לו קשר עם ההגדרות ב Web.config עצמו של האפליקציה ככה היה ניתן להגדיר ל 2 דומנים שונים שמצביעים על אותה תקייה עם 2 Default Document שונים.

כאשר ננסה לעשות הגדרה של 2 Default Document  ב IIS 7 ה Web.config השתנה לפי הדומיין שבחרנו באותו רגע, יש כמה שיטות לטפל בבעיה דרך URL Rewirte כחלק מה IIS 7 , הפניות ב JAVA SCRIPT כ REDIRECT או דרך עריכה של ה  Application Host שעליו אני ירחיב.

Application Host זה קובץ הממוקם בהגדרות של ה IIS, הוא ממוקם בספרייה:
C:\Windows\System32\inetsrv\config\applicationHost.Config

יש לפתוח את הקובץ (חשוב מאוד לגבות לפני תחילת התהליך!!):
יש להוסיף את בלוק למטה לפני <configuration/ > שסוגר את בלוק המרכזי של הקובץ.

<location path="your_site_name_in_the_iis">
        <system.webserver>
           <defaultdocument>
             <files>
                  <add value="my default document.aspx">
            </files>
          </defaultdocument>
        </system.webserver>
</location>

דרך נוספת לבצע את התהליך זה דרך ה Command Line - CMD:

%windir%\system32\inetsrv\appcmd.exe set config "[your site name in the iis]" -section:system.webServer/defaultDocument -+files.[value="my default document.aspx"] -commitpath:apphost

בהצלחה...

יום שלישי, 7 בספטמבר 2010

Disable SSL 2 Windows 7


מסתבר שגרסה של WINDOWS SERVER 2008 SP1 מגיעה עם SSL 2 כברירת מחדל, כחלק מעמידה בתקן PCI DSS חובה לעבוד עם SSL 3 ו TLS 1.

על מנת להוסיף תמיכה ב SSL 3 וב TLS 1 יש לפתוח את ה REGEDIT.

1.להיכנס לספרייה:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols

יש ליצור שני מפתחות חדשים:
SSL 3.0
TLS 1.0

לדוגמה:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols\SSL 3.0

בכל אחד מהמפתחות יש ליצור 2 מפתחות נוספים:
Client
Server

לדוגמה:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols\SSL 3.0\Client\

לכל מפתח (CLIENT או SERVER)צריך להוסיף DWORD 32 BIT VALUE בשם: ENABLED עם VALUE = 1.
כאשר ה VALUE = 1 המערכת תומכת וכאשר הוא 0 היא לא.

נחזור למפתח SSL 2.0 ונבחר את ה DWORD שבתוכו (DisableByDefault או ENABLED ) ונשנה ל VALUE = 0

עכשיו יש לנו תמיכה ב SSL 3 \ TLS 1.0 , אבל זה לא מספיק צריך לוודא שאין WEAK CIPHERS במקרה שלי היה רק WEAK CIPHERS שהם מאוד חלשים במפתח הצפנה שלהם עד שהם ניתנים לחיזוי ע"י התוקפים.

נפתח את המפתח:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Ciphers
ונבנה בתוכו שלושה מפתחות חדשים:
RC2 128/128
RC4 128/128
Triple DES 128/128

לדוגמה:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel\Ciphers\RC2 128/128

שדרגנו את המפתח הצפנה.

בהצלחה...








יום שני, 16 באוגוסט 2010

ODBC 3.51 windows server 2008 64bit

אחרי כל הצרות שעברתי עם ה IIS 7 עכשיו נוצרו בעיות אחרות איך אני מתחבר לאפליקציות ישנות שמשתמשות בחיבור ODBC ישן כמו גרסה 3.51.

על מנת להפעיל את ה ODBC יש להוריד 2 גרסאות מהאתר של MYSQL:


1.את הגרסה ה 32 BIT


2.את הגרסה 64 BIT


יש להתקין את הגרסה 32 BIT ע"י קובץ ההתקנה המצורף.
אך עדיין לא נראה את הגרסה מותקנת Data Sources (ODBC).
את הגרסה 64 BIT יש לפתוח מה ZIP להפעיל CMD ולרשום:
C:\mysql-connetctor>install.bat 0
0 - מסמן התקנה של הגרסת RELEASE.
1 - מסמן התקנה של הגרסה DEBUG.

לאחר סיום ההתקנות יש להפעיל את ה IIS מחדש, ויש לכם ODBC גרסה 3.51.

בהצלחה.