13

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

Snack3r

السلام عليكم

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

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

تحياتي.


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

فضيحة كبيرة للجافا؟ جميع اللغات يوجد فيها 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 هل يمكنك إرجاع ولو سطر واحد من البرنامج؟

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