Overthewire Vortex0 Write-Up

بسم الله الرحمن الرحيم 

اللهم لا علم لنا الا ماعلمتنا انك انت العليم الحكيم

راح نتجاوز التحدي المطروح على http://overthewire.org/wargames/vortex/vortex0.html

الشرح راح يكون على
vortex.labs.overthewire.org

وهو موقع يحاكي اختبار الاختراق

التحدي كان

كود:
Your goal is to connect to port 5842 on vortex.labs.overthewire.org and read in 4 unsigned integers in host byte order. Add these integers together and send back the results to get a username and password for vortex1.
يعني الهدف الوصول الى السيرفر عن طريق البورت 5842 ومحاولة معرفة اليوزر والباس

تعالوا نشوف لو نتصل بالنت كات وش يعطينا



نشوف الرد كان غير مفهوم والرد بمثل هذي الطريقة يطلع اذا كان نوع الداتا المستخدم غير

الموقع يقول ان نوع الداتا unsigned integers وبنفس الوقت لازم نظيفها على بعض ونرجع نرسلها للموقع عشان يعطينا اليوزر والباس


الان نخش في العميق

ولابد يكون لك خلفية في السي لاني الموضوع معتمد على السي وايضا على السوكيت

تعتبر السي من اقوى انواع البرمجة ولا يقارن بها شي تقريبا
كود:
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<string.h>    //s
#define MAXDATA 4096
اول شي نقوم باضافة الهيدر والمكتبات اللازمة للاستخدام في عملنا

وعرفنا MAXDATA ب 4096 يعني في كل مره يتصل السوكيت يقدر يستقبل 4 كيلوبايت
كود:
int main (int argc , char *argv[])
بداية الكود تبعنا

واستخدمنا (int argc , char *argv[]) لان الروتين main يعود بقيمة ولو كان مايعود باي قيمة لغيرناه الى void
كود:
int num;
        int socket_con;
        struct sockaddr_in server;
        char reply[MAXDATA];
        uint32_t sum = 0;
        unsigned int i;
        uint32_t result;
        char *ip = argv[1];
اول متغير من نوع int num وعادة ماياخذ اربع بايتات في اغلب الاجهزة الحديثة والمتغير num لحساب عدد البايتات

المتغير الثاني int socket_con عشان نسوي سوكيت به ولاحظوا انه int لان العائد من صنع السوكيت يكون intger عشان كذا استخدمنا int

بعدين struct sockaddr_in server وهو ستركتشر struct خاص بنوع ipv4 ويحتوي على
كود:
struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};
بعدين char reply[MAXDATA] وهو من نوع الكاركتر مصفوفة لاستقبال الرد وتخزينه

واهم شي

uint32_t sum = 0;

والنوع هذا هو unsigned integers ولكن على البروسسر 32bit ولو اختلف النوع راح يطلع لما مثل ماطلع في الاتصال بالنت كات

بعدين unsigned int i; عشان نسوي لوب , شوي وبتفهمون

uint32_t result; النتيجة النهائية
كود:
char *ip = argv[1];
الان صار بالامكان وضع الاي بي في الخانة الاولى بعد المسافة على سطر الاوامر ولاحظوا انه بوينتر

الان نبدا نبرمج
كود:
socket_con = socket(AF_INET,SOCK_STREAM,0);

if (socket_con == -1)
        {
                printf ("Connection error\n");

}
اول شي سويناه عشان نتصل لازم نسوي سوكيت وعيناه مع المتغير socket_con

السوكيت ياخذ ثلاث قيم الاولى هي domain/family وبما اننا على IPv4 استخدمنا AF_INET

القيمة الثانية SOCK_STREAM وهو يحدد transport layer protocol يعني tcp or udp

القيمة الثالثة عادة تترك 0 <- راجعوها

ومثل ماقلت يرجع لنا بقيمة انتجر وهو عدد صحيح

وقلنا اذا كان يساوي -1 يعني ماصنع السوكيت اكتب لنا Connection error

بعدين نكون السيرفر تبعنا

اللي بيتصل ويحمل خصائص الاتصال
كود:
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ip);
server.sin_port = htons(5842);
الدالة inet_addr تستخدم لتحويل string الى عدد صحيح

htons معناها host to network string

نكمل
كود:
if(connect(socket_con ,(struct sockaddr *)&server, sizeof(server)) < 0)
        {
                printf("Conection error\n");
                return 1;


}
هنا بعد ماكوّنا السوكيت والسيرفر نبدا نتصل بالدالة connect

وتاخذ القيم
كود:
connect (int socket, struct sockaddr *addr, socklen_t length)
والدالة ذي ننتظر السيرفر حتى يرد وعادة ترجع بالقيمة 0 اذا مافيه اي خطا والاتصال تم

نكمل الكود
كود:
for(i=0;i<=3;i++) {
                recv(socket_con, &result, 4, 0);
                sum += result;
        }
write(socket_con,&sum, 4);
الان نسوي لوب لاربع مرات وكل مره راح نستقبل اربع بايتات يعني المجموع يكون 16
 وسويت لوب اربع مرات لان التحدي يقول unsigned integers وكل واحد فيهم ياخذ اربع بايتات يعني
 اربع حروف

واستخدمت الدالة recv وتاخذ القيم
كود:
 recv(int socket, void *buffer, size_t length, int flags);
وكتبت البايتات المستقبلة للرفرنس تبع sum اللي هو في الاساس result

نكمل
كود:
if ((num = recv(socket_con,reply,MAXDATA,0)) == -1 ) 
{
printf("recv fails\n");
}


printf("%s\n",reply);
return 0;


}
هنا نشوف عدد البايتات في الدالة recv اذا هي -1 يعني الدالة ماستقبلت شي واذا اكبر يعني الدالة استقبلت البايتات

وبالاخير نطبع البايتات المستقبلة

نشوف



فعلا استقبلنا اليوزر والباس

الكود كامل

ان اعجبك فاذكر الله وادع لي وان لم يعجبك فانصحني لاصبح افضل

كود:
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<string.h>    //s
#define MAXDATA 4096 
int main (int argc , char *argv[])
  {
 
 int num;
 int socket_con;
 struct sockaddr_in server;
 char reply[MAXDATA]; uint32_t sum = 0;
 unsigned int i;
 uint32_t result;
 char *ip = argv[1];
socket_con = socket(AF_INET,SOCK_STREAM,0);

if (socket_con == -1)
 {
  printf ("Connection error\n");

}

server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ip);
server.sin_port = htons(5842);

if(connect(socket_con ,(struct sockaddr *)&server, sizeof(server)) < 0)
 {
  printf("Conection error\n");
  return 1;


}
for(i=0;i<=3;i++) {
  recv(socket_con, &result, 4, 0);
  sum += result;
 }
write(socket_con,&sum, 4);


if ((num = recv(socket_con,reply,MAXDATA,0)) == -1 ) 
{
printf("recv fails\n");
}


printf("%s\n",reply);
return 0;


}  

تعليقات

المشاركات الشائعة من هذه المدونة

CRLF injection [\r\n Carriage Return]

Study in Nosql-Injection-Mongodb