13

كيف تحمي الـ source code بعد تحويل المشروع إلى executable jar ؟

السلام عليكم

أنا عضو جديد في هذه المنصة، مشرف سابق في منتديات الفريق العربي للبرمجة و rédacteur أيضاً في Club des développeurs et IT Pro.

أعجبتني فكرة الموقع و أحببت أن أناقش معكم كيفية حماية ملف الـ jar إذا كان المشروع غير مفتوح المصدر.

تحياتي.


التعليق السابق

هذه فضيحة كبيرة للجافا!

قمت بفتح عدد كبير من المكتبات والـ JAR والـ CLASS بهذا البرنامج، وقد أظهر كل الكود المكتوب، لم يتبقى إلا التعليقات comments هي التي لم تظهر

أعتقد أن هذا يُثبت أن لغة جافا لا ترقى لأن تكون compiled language لأن من صفات الـ compiled language أن تقوم بإصدار برامج تنفيذية ثُنائية. لكن هذا البرنامج يُثبت أنها ليست برامج ثُنائية حقيقية

سؤال آخر، هل برامج اﻷندرويد المكتوبة بالجافا ايضاً يحدث لها Decompilation? الـ APK

فضيحة كبيرة للجافا؟ جميع اللغات يوجد فيها decompilation. على أية حال، توجد أدوات وبرامج تقوم بتحويل برامج الجافا من byte-code إلى native-code، وبالتالي لن تستطيع إعادة كود الجافا الأصلي، ولكن يمكن الإعادة لكود السي/سي بلص بلص، وأيضاً لن تستطيع تشغيل البرنامج على الأنظمة الأخرى.

هل توجد للغات مثل سي ودلفي إمكانية عمل decomplication دلني على تلك اﻷداة إذا امكن. وماهي البرامج التي تقوم بتحويل كود الجافا إلى native code?

هل توجد للغات مثل سي ودلفي إمكانية عمل decomplication دلني على تلك اﻷداة إذا امكن

بالنسبة لـ C فيوجد[1] لكن المشكلة المترجمات Compilers لا تنتج نفس الكود حتى بدون تحسين الكود(أحد خيارات GCC)

هذا الكود مثالا

-

مترجم MinGW مع Codeblocks ينتج

بداية البرنامج

-

الدالة Main

-

مترجم OpenWatcom مع IDE (يأتي معه في نفس الحزمة)

بداية البرنامج

-

الدالة Main

نرى الاختلاف كبير مع أنه نفس الكود !

-

[1]

هل يُمكنك عمل إجراء أكثر تعقيد بلغة سي، مثلاً الكتابة في ملف نصي، ومعرفة كيف يتم إعادة الكود.

تقصد المثال أم البرنامج

اقصد بدلاً من HelloWorld قم بكتابة برنامج لقراءة أو كتابة ملف ثم محاولة إرجاع المصدر الأصلي

الكود الأصلي ترجمته بـ MinGW مع CodeBlocks

-

int main()
{
    FILE *fp;
    fp = fopen("out.txt","w+");
    fprintf(fp,"Hello World!");
    fclose(fp);
    return 0;
}

-

الكود المولد من Hex-Rays IDA 6.1

int __fastcall sub_401010(int a1, char a2)
{
  char v2; // ST08_1@1
  int v3; // eax@1
  int v4; // ecx@1
  int v5; // edx@1
  v2 = a2;
  v3 = sub_4012A0("out.txt", (int)&unk_409004, a1);
  sub_4013A0(v4, v3, v3, (int)"Hello World!", v2);
  sub_401490(v5);
  return 0;
}

ملاحظة:

تجاهلت دوال المكتبة القياسية التي تم توليدها

هذا كود Assembly الذي تم توليد كود C منه

-

sub_401010 proc near
   push    edx
   mov     edx, offset unk_409004
   mov     eax, offset aOut_txt ; "out.txt"
   call    sub_4012A0
   push    offset aHelloWorld ; "Hello World!"
   push    eax
   mov     edx, eax
   call    sub_4013A0
   add     esp, 8
   mov     eax, edx
   call    sub_401490
   xor     eax, eax
   pop     edx
   retn
sub_401010 endp

شكراً لك.

طلب أخير، قمت بعمل برنامج للكتابة في ملف نصي ثم عرضه بواسطة فري باسكال/لازاراس

هل يُمكنك إعادة المصدر ثم عرضه هنا.

البرنامج في هذا الرابط:

هناك أمورا نسيت أن أذكرها

عند توليد كود البرنامج مكتوب بـ C ستحصل على :

  • كود إبتدئي يحصل على المعلومات التي تحتاجها المكتبات ( ... ,Argc, Argv, stdin, stdout, stderr)

  • كود المكتبات المدمج مع البرنامج Static Library مثل (printf,fopen, ...)

  • كود معالج الإستثنائات

  • كود الذي يكتبه المبرمج

حتى تجد كود المبرمج عليك أن تعرف متى يبدأ كود المكتبة ومتى ينتهي

وهذا يختلف مع كل مترجم لغة(ما يولده MinGW غير الذي يولده ++MVC)

أما في حالة Free Pascal فأنا لا أعرف كيف يولد البرامج وما هي بنية مكتباته

حتى أستطيع الفصل بينه وما كتبت

لكن على كل حالة رفعة لك الكود المولد عن المثال الذي طلبته

والكود المولد عن FileSample

-

صورة توضيحية على ما ذكرتُ

الكود الإبتدائي ما قبل Main

شكراً لك أخ طالب علم

هذا مطمئن بأن البرامج الطبيعية Native لا يمكن إرجاعها إلى مصدرها الأصلي بسهولة. حتى لو تم إرجاعها فلا يمكن تعديلها وإعادة ترجمتها.

ونستخلص من الملف الذي أرسلته اﻵتي:

  1. لم يتم التعرف على لغة البرمجة اﻷصلية التي أنتجت الملف الثُنائي، حيث استخدمت مترجم فري باسكال أما برنامج الـ Decompiler فقط افترض أنها Visual C++, هذا جزء من ترويسة الملف الناتج:

    /* This file has been generated by the Hex-Rays decompiler.
       Copyright (c) 2007-2011 Hex-Rays <info@hex-rays.com  >
    
     Detected compiler: Visual C++
     */
    
    #include <windows.h>
    #include <math.h>
    #include <defs.h>
    
  2. أسماء المتغيرات والدوال غير موجودة في البرنامج الناتج.

  3. ليس هُناك علاقة بين حجم البرنامج اﻷصلي والناتج. حيث أن البرنامج اﻷصلي حوالي 50 سطر، أما الناتج فهو 198 ألف سطر!

  4. هذا البرنامج تمت كتابته في حوالي 5 دقائق، لم يستطع الـ Decompiler بإرجاعه بصورة مفهومة، فكيف البرامج التي تحتاج لسنوات للتطوير.

هذا نص البرنامج اﻷصلي:

unit main;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  LCLIntf;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var  
  F: TFileStream;
begin  
  F:= TFileStream.Create('file.txt', fmCreate);
  F.WriteAnsiString('Hello there' + #13#10);
   F.WriteAnsiString('Today is: ' + DateTimeToStr(Now));
  F.Free;
    OpenDocument('file.txt');

end;

end.

هل توافق على هذه الاستنتاجات؟ لأني أريد البناء عليها في المستقبل

1)

برنامج Hex-Rays IDA لا يفرق بين المترجمات،

هناك برنامج يسمى Exeinfo PE يستطيع معرفة مترجم الذي ترجم البرنامج

الأخيرة MinGW لم يتعرف عليه بالتفصيل لكنه يبقى GCC

-

2)

صحيح ولن يستطيعوا إيجادها

-

3) السبب هو المكتبة القياسية المدمجة في البرنامج

فالكود المولد هو

كود المبرمج + كود المكتبة القياسية

-

4) IDA هو Disassembly ليس متخصص في Free Pascal أو MinGW أو غيرهما

هناك برامج متخصص مثل Java Decompiler الفرق أن الجافا أسهل من غيرها

-

هل توافق على هذه الاستنتاجات؟ لأني أريد البناء عليها في المستقبل

فيما يتعلق بأسماء المتغيرات والدوال من غير المكتبة القياسية، نعم

مكتبة STL القياسية في ++C صعب على Decompiler التعرف إليها

حتى لو كان متخصص بسبب طبيعة Templates المتغيرة

أريد أن أضيف كلما زاد تعقيد البرنامج كلما اعتمد على مكتبات إضافية أكثر، بهذه الطريقة يصعب إرجاعه إلى اﻷصل

وايضاً أن لغات البرمجة الـ Native تعتمد على نداء مكتبات موجودة في نظام التشغيل بشكل أساسي

والباسكال لديه مكتبة قياسية ذات حجم كبير، لذلك البرامج التنفيذية المكتوبة بلغة اوبجكت باسكال كبيرة جداً مقارنة بالسي

هذا مثال يرسم شكل معين على الطرفية

أخترته لأنه يحمل خوارزمية أعقد من المقترح

الكود الأصلي

int main()
{
  int n, c, k, space = 1;
  printf("Enter number of rows\n");
  scanf("%d", &n);
  space = n - 1;
  for (k = 1; k <= n; k++)
  {
    for (c = 1; c <= space; c++)
      printf(" ");
    space--;
    for (c = 1; c <= 2*k-1; c++)
      printf("*");
    printf("\n");
  }
  space = 1;
  for (k = 1; k <= n - 1; k++)
  {
    for (c = 1; c <= space; c++)
      printf(" ");
    space++;
    for (c = 1 ; c <= 2*(n-k)-1; c++)
      printf("*");
    printf("\n");
  }
  return 0;
}

ترجمته بـ MinGW مع CodeBlocks

الكود المولد من HexRays IDA 6.1

int __fastcall sub_401010(int a1, int a2)
{
  int v2; // edx@1
  int v3; // ecx@1
  signed int v4; // edi@1
  int v5; // ecx@1
  signed int v6; // esi@2
  int i; // edx@3
  int v8; // edx@4
  int v9; // edx@5
  int j; // ecx@5
  int v11; // edx@6
  signed int v12; // ebx@8
  int k; // ecx@8
  int l; // edx@10
  int v15; // edx@11
  int v16; // edx@12
  int v17; // edx@14
  int v18; // ecx@15
  int v20; // [sp+0h] [bp-1Ch]@1
  sub_401110(a1, a2, (int)"Enter number of rows\n", v20);
  sub_4011B0(v3, v2, (int)"%d", (unsigned int)&v20);
  v4 = 1;
  v5 = v20 - 1;
  if ( v20 >= 1 )
  {
    v6 = 1;
    do
    {
      for ( i = 1; i <= v5; i = v8 + 1 )
        sub_401110(v5, i, (int)" ", v20);
      v9 = 1;
      for ( j = v5 - 1; v9 <= v6; v9 = v11 + 1 )
        sub_401110(j, v9, (int)"*", v20);
      sub_401110(v5, v9, (int)"\n", v20);
      ++v4;
      v6 += 2;
    }
    while ( v4 <= v20 );
  }
  v12 = 1;
  for ( k = 1; k <= v20 - 1; k = v18 + 1 )
  {
    for ( l = 1; l <= v12; l = v15 + 1 )
      sub_401110(k, l, (int)" ", v20);
    v16 = 1;
    ++v12;
    while ( v16 <= 2 * (v20 - k) - 1 )
    {
      sub_401110(k, v16, (int)"*", v20);
      v16 = v17 + 1;
    }
    sub_401110(k, v16, (int)"\n", v20);
  }
  return 0;
}

ملاحظة:

تجاهلت دول المكتبة القياسية التي تم توليدها

لدي برنامج مكتوب بلغة Free Pascal وهي native compiled هل يمكنك إرجاع ولو سطر واحد من البرنامج؟

يمكنك تحميله من هذا الرابط:

أعتقد أن هذا يُثبت أن لغة جافا لا ترقى لأن تكون compiled language

لأن من صفات الـ compiled language أن تقوم بإصدار برامج تنفيذية ثُنائية.

لكن هذا البرنامج يُثبت أنها ليست برامج ثُنائية حقيقية

جربتها على لعبة Minecraft وظهر الكود واضح وصريح لكن لم تكن الاسماء مفهومة كانت على شاكلة a aa ab ac

ربما يكون في المترجم Compiler خيار لتشفير الأسماء

سؤال آخر، هل برامج اﻷندرويد المكتوبة بالجافا ايضاً يحدث لها Decompilation? الـ APK

ربما، لم أجرب فعل ذلك

قد يفيدك هذا الرابط

بنسبة للموضوع الأندريود هناك برامج قامت بDecompilation وأضف إلي ذلك إني تمكنت إضافة سطر إلي لغة جافا أقصد لغة الألة خاصة بجافا إلي لعبة Subway وعمل :) لا أعرف هل لغة جافا ضعيفة إلي هذه الدرجة أو لا وللعلم أنا لأعرف شي عن جافا إلا قليل

ممكن توضيح لهذه النقطة :

أضف إلي ذلك إني تمكنت إضافة سطر إلي لغة جافا أقصد لغة الألة خاصة بجافا إلي لعبة Subway وعمل

أنا أقصد أن أعدل علي ملفات smali,سأعطيك مثال

smali code

const/4 v1, 0x1

if-ne v0, v1, :cond_0

const/4 v2, 0x2

move v0,v2

goto :goto_0

:cond_0

const/4 v2, 0x3

move v0,v2

:goto_0

أوكي اتضحت الفكرة.

لا أعرف هل لغة جافا ضعيفة إلي هذه الدرجة أو لا وللعلم أنا لأعرف شي عن جافا إلا قليل

ماذا كنت تريدها أن تفعل ؟ :)

لا شي بس أريد أن أوضح العيب في لغة جافا لا غير لا يوجد شي كامل

أريد أن أوضح العيب في لغة جافا

هل العيب في وجهة نظرك هو بساطة عمل decompilation لملف الـ jar أم عدم تعرف الـ JVM على التغيير اليدوي لبنية ملف الـ smali ؟

لا يوجد شي كامل

هذا أمر بديهي، لغات البرمجة عمل بشري و الكمال لله وحده ! :)

-4

الفضيحة الحقيقية هي أن تتكلم في شيء لا تعرفه.

وماهو الشيء الذي لا أعرفه ؟

في الحقيقة كُنت استخدم جافا لأكثر من ثلاث أعوام. وقد سمعت أنه يمكن إعادة مصدر الكود من البرنامج التنفيذي، لكن لم اكن أتوقع أن يكون الموضوع بهذه السهولة، وحتى أسماء المتغيرات والكلاسات واﻹجراءات و الدوال تظهر بكل سهولة. والمشكلة أن من قام بعمل decomplication هم جهة أخرى أي third party. والمشكلة اﻷكبر أنه لا يمكن الحيلولة دون الـ decomplication على حسب هذه الصفحة:

بالمناسبة يا اﻷخ القادم من المنتديات. لدي برنامج جافا يعمل في موريتانيا منذ عام 2012

لدي برنامج جافا يعمل في موريتانيا منذ عام 2012

ماذا تقصد؟

هذه عبارة عابرة لأني عرفت أنه من موريتانيا

ولي عدد من اﻷصدقاء هُناك، وهم يمتازون باللباقة في الحديث والتواضع

-2

يعني أن حديثي ليس لبقاً و لستُ شخصاً متواضعاً، شكراً لك ! :)

لا لم اقصد هذا، لكن قصدت أنك أول شخص مختلف أقابله من موريتانيا

-2

اسف في التدخل

ولي عدد من اﻷصدقاء هُناك، وهم يمتازون باللباقة في الحديث والتواضع

أنك أول شخص مختلف أقابله من موريتانيا

هل هذه عنصرية ؟

يقصد به الرد على :

الفضيحة الحقيقية هي أن تتكلم في شيء لا تعرفه.

أي أنه يعرف ، وليس كما تفضل الأخ الأخر بإسلوب تقليل من علم الأخ معتز :)

-2

جيد، لكن ما علاقة هذا بالموضوع ؟ :)

اقصد أني عملت برامج تجارية بالجافا وهي تعمل في بلدك.

هل عملت برامج حقيقية واستفاد منها الناس بلغة جافا؟

نعم ! وبالسي و السي++ أيضاً :)

أخي الكريم أنا لا أقلل من علمك و لكن للأسف أنت لا زلت تزيد قناعتي بأنك تتحدث عن موضوع لا تتقنه مع احترامي الشديد لك :)

أعتقد أن هذا يُثبت أن لغة جافا لا ترقى لأن تكون compiled language

من قال بأن جافا compiled language ؟ لو قرأت عن الجافا قليلا لعلمتَ أنها semi-compiled و شتان ما بين الأمرين.

وقد سمعت أنه يمكن إعادة مصدر الكود من البرنامج التنفيذي، لكن لم اكن أتوقع أن يكون الموضوع بهذه السهولة

في الجافا لا يوجد إطلاقا شيء اسمه "ملف تنفيذي" إن كنت تقصد ملف exe لأن بنية ملف الـ jar تختلف تماما عن بنية exe.

أخي الكريم أنا لا أقلل من علمك و لكن للأسف أنت لا زلت تزيد قناعتي بأنك تتحدث عن موضوع لا تتقنه مع احترامي الشديد لك :)

أنت أيضاً تزيد قناعتي أنك لا تعرف الكثير عن الجافا، وانك لم تكتب بها برامج حقيقية مع كامل احترامي لك :)

من قال بأن جافا compiled language ؟ لو قرأت عن الجافا قليلا لعلمتَ أنها semi-compiled و شتان ما بين الأمرين.

التحويل من source code إلى byte code ليتم تنفيذه بواسطة الـ virtual machine هي عملية complition

في الجافا لا يوجد إطلاقا شيء اسمه "ملف تنفيذي" إن كنت تقصد ملف exe لأن بنية ملف الـ jar تختلف تماما عن بنية exe.

ملفات الـ JAR هي ملفات تنفيذية، في نظام لينكس تقوم بإعطاها صلاحية execute حتى يتم تنفيذها مباشرة من الـ file explorer

التحويل من source code إلى byte code ليتم تنفيذه بواسطة الـ virtual machine هي عملية complition

غير صحيح، javac يقوم بتحويل .java إلى .class (هذه العملية تُسمى compilation) بعد ذلك تقوم الـ JVM بتحميل الـ byte code و عمل interpretation له كما يُمكنها أيضاً أن تقوم بعمل JIT.

لهذا قُلت لك أن الجافا ليست compiled language بل هي semi-compiled لأن عملية الترجمة أو التفسير تتم على مرحلتين.

ملفات الـ JAR هي ملفات تنفيذية، في نظام لينكس تقوم بإعطاها صلاحية execute حتى يتم تنفيذها مباشرة من الـ file explorer

أنا كنت أتحدث عن الويندوز و ملفات exe، الـ jar اختصار لـ Java ARchive و هو ليس ملفا تنفيذياً من حيث البنية (كلامي واضح جداً) لأن ملف الـ Jar عبارة عن ملف ZIP و يُمكنك رؤية محتواه باستخدام WinRar مثلا.

نعم هو ملف مضغوط، يحتوي على classes تنفيذية، أي يمكن تنفيذها كأنها ملف ثنائي. وفي النهاية آلة جافا اﻹفتراضية تقوم بتحويل الـ byte code إلى برنامج ثُنائي حسب نظام التشغيل في الذاكرة لتنفيذه.