Analisis Self Modifying Code Menggunakan Dynamic Binary Instrumentation

(1)

(2)

(3)

(4)

Nama Lengkap : Teguh Prima Alko Jenis Kelamin : Pria

Tempat, Tanggal

lahir : Pangkal Pinang, 2 Maret 1992

Kewarganegaraan : Indonesia Status Hubungan : Belum Menikah Tinggi , Berat : 175 cm , 73 kg

Agama : Islam

Alamat Lengkap : JL. R.H Fisabilillah No. 7 Tanjungpinang

Handphone : 081224746230

E-mail : teguh@cloudmail.de

RIWAYAT PENDIDIKAN

1998 – 2003 : SD Negeri 23 Tanjungpinang 2003 – 2006 : SMP Negeri 4 Tanjungpinang 2006 – 2009 : SMA Negeri 2 Tanjungpinang

2009 – 2016 : Universitas Komputer Indonesia, Fakultas Teknik dan Ilmu Komputer, Jurusan S1 Teknik Informatika


(5)

Diajukan untuk Menempuh Ujian Akhir Sarjana

TEGUH PRIMAALKO 10109383

PROGRAM STUDI TEKNIK INFORMATIKA

FAKULTAS TEKNIK DAN ILMU KOMPUTER

UNIVERSITAS KOMPUTER INDONESIA

2016


(6)

iii

Sudah semestinya penulis berterimakasih kepada Allah Subhanahu wa

ta’ala yang telah memberikan energi untuk dapat menyelesaikan skripsi yang

berjudul “ANALISIS SELF-MODIFYING CODE MENGGUNAKAN

DYNAMIC BINARY INSTRUMENTATION”.

Maha kuasa Allah Subha nahu wa ta’ala telah mengirim anugerah dengan

orang-orang yang dapat menemani, membimbing dan mendukung penyelesaian skripsi ini dengan cara yang sangat luar biasa. Untuk itu, penulis ingin menyampaikan rasa terimakasih sebesar-besarnya kepada:

1. Ibunda penulis yang telah memberikan doa dan pengertian serta Suci A. Ayu sebagai adik dari Penulis yang telah memberikan dukungan.

2. Bpk. Adam Mukharil Bachtiar, S.Kom., M.T., sebagai pembimbing yang memotivasi dan memberikan pemahaman yang jernih kepada penulis.

3. Adrian Negreanu dan Derek Bruening sebagai pengembang DynamoRIO yang bersahabat dalam memberikan petunjuk

4. Aluh yang bersih keras agar Penulis tetap berjuang sampai lulus, Ipey dengan nasihat dan konsep kedewasaanya, Domse yang selalu percaya diri dengan absurdity-nya, Olih yang selalu menebar tawa ketika down, Tetski dengan kelucuan emosionalnya dan Didiw sebagai sahabat travelling dan refreshing ketika jenuh

5. Rekan-rekan seperjuangan skripsi yang ikhlas memberikan informasi kepada Penulis yakni Rizkika Adam dan Arif serta Ali yang memberikan cheer up dengan penuh determinasi

6. Yellow Truck, Bobber Cafe, Goethe-Institut, Double Eight Coffee dan Caffetto atas ruang yang cozy dan kopi nikmatnya


(7)

iv

Bandung, 2 Maret 2016


(8)

v

ABSTRACT ... ii

KATA PENGANTAR ... iii

DAFTAR ISI ... v

DAFTAR GAMBAR ... viii

DAFTAR TABEL ... ix

DAFTAR LAMPIRAN ... xi

BAB I PENDAHULUAN ... 1

I.1 Latar Belakang Masalah ... 1

I.2 Perumusan Masalah ... 2

I.3 Maksud dan Tujuan Penelitian ... 2

I.4 Batasan Masalah ... 2

I.5 Metodologi Penelitian ... 3

I.6 Sistematika Penulisan ... 5

BAB II TINJAUAN PUSTAKA ... 7

II.1 Debugging ... 7

II.2 Macam-Macam Format Debugging ... 7

II.3 Instrumentation ... 8

II.4 Metode Binary Instrumentation ... 10

II.5 ELF ... 10

II.6 Self-Modifying Code ... 11


(9)

vi

II.11 Binary Analysis ... 19

II.12 Program Lifecycle Phase ... 20

II.12.1 Edit Time ... 20

II.12.2 Compile Time... 20

II.12.3 Link Time ... 20

II.12.4 Load Time ... 21

II.12.5 Run Time ... 21

II.13 Binary Translation ... 21

II.14 Intermediate Representation ... 21

BAB III ANALISIS SELF-MODIFYING CODE DAN PERANCANGAN DYNAMIC BINARY INSTRUMENTATION ... 23

III.1 Analisis Sistem ... 23

III.1.1 Analisis Masalah ... 23

III.1.2 Analisis Biner Program ... 23

III.1.3 Analisis Self-Modifying ... 24

III.1.4 Analisis Binary Translation ... 28

III.1.5 Analisis Sintaksis ... 30

III.1.6 Spesifikasi Intermediate Representation ... 41

III.1.7 Analisis Kebutuhan Non Fungsional ... 50

III.1.7.1. Analisis Perangkat Lunak ... 51

III.1.7.2. Analisis Perangkat Keras ... 51


(10)

vii

IV.1.1. Lingkungan Implementasi Sistem ... 63

IV.1.2. Implementasi Pembangunan Dynamic Binary Instrumentation ... 63

IV.1.3. Implementasi Pembuatan Random Test Case Generation ... 65

IV.2 Pengujian Sistem ... 65

BAB V KESIMPULAN DAN SARAN ... 75


(11)

77

Instrumentation,” in VEE '12 Proceedings of the 8th ACM SIGPLAN/SIGOPS conference on Virtual Execution Environments, New York, 2012.

[2] M. Probst, “Dynamic Binary Translation,” CD Laboratory for Compilation Techniques, 2003.

[3] N. Mavrogiannopoulos, N. Kisserli and B. Preneel, “A taxonomy of self -modifying code for obfuscation,” Computers and Security, vol. 30, no. 8, pp. 679-691, 2011.

[4] N. Nethercote, “Dynamic Binary Analysis and Instrumentation,” University of Cambridge Computer Laboratory, 2004.

[5] “The DynamoRIO API,” Google, 8 October 2015. [Online]. Available: http://dynamorio.org/docs/.

[6] K. Anand, M. Smithson, K. Elwazeer, A. Kotha, J. Gruen, N. Giles and R.

Barua, “A Compiler-level Intermediate Representation based Binary Analysis

and Rewriting System,” in EuroSys '13 Proceedings of the 8th ACM European Conference on Computer Systems, New York, 2013.

[7] “ELF,” OS Development, 7 August 2015. [Online]. Available: http://wiki.osdev.org/ELF.

[8] X. Xie, F. Liu, B. Lu and F. Xiang, “Mixed Obfuscation of Overlapping Instruction and Self-Modify Code Based on Hyper-Chaotic Opaque

Predicates,” in Computational Intelligence and Security (CIS), Kunming, 2014.


(12)

[9] S. Blazy, V. Laporte and D. Pichardie, “Verified Abstract Interpretation Techniques for Disassembling Low-level Self-modifying Code,” in Interactive Theorem Proving, Springer International Publishing, 2014, pp. 128-143.

[10] B. Anckaert, M. Madou and K. D. Bosschere, “A Model for Self-Modifying

Code,” in Information Hiding, Springer Berlin Heidelberg, 2007, pp. 232-248.

[11] T. Touili, B. Cook and P. Jackson, “Computer Aided Verification,” in 22nd International Conference, CAV 2010, Edinburgh.

[12] N. M. Hai, M. Ogawa and Q. T. Tho, Obfuscation code localization based on CFG generation of malware, Clermont-Ferrand: Springer, 2015.

[13] R. Mankadan, P. A. Kumar and R. Govindaraju, “CODE SECURITY BY

CONFUSING LOGIC FLOW USING SELF MODIFYING CODE,”

International Journal of Innovative Trends and Emerging Technologies, vol. I, no. 2, 2015.

[14] J. Pogulis, “Generation of dynamic control-dependence graphs for binary

programs,” Linköping University, Department of Computer and Information

Science, Database and information techniques, 2014.

[15] M. Payer, A. Barresi and R. T. Gross, “Lockdown: Dynamic Control-Flow

Integrity,” ETH, Zürich, 2014.

[16] W. Arthur, B. Mehne, R. Das and T. Austin, “Getting in control of your control flow with control-data isolation,” in CGO '15 Proceedings of the 13th Annual IEEE/ACM International Symposium on Code Generation and Optimization, 2015.


(13)

[17] V. Pappas, M. Polychronakis and A. D. Keromytis, “Dynamic Reconstruction of Relocation Information for Stripped Binaries,” in Research in Attacks, Intrusions and Defenses, Springer International Publishing, 2014, pp. 68-87. [18] T. Vilkeliskis, “Automated unpacking of executables using Dynamic Binary

Instrumentation,” Department of Computer Science, Stevens Institute of

Technology, 2009.

[19] . A. Roy, S. Hand and T. Harris, “Hybrid binary rewriting for memory access

instrumentation,” in VEE '11 Proceedings of the 7th ACM SIGPLAN/SIGOPS international conference on Virtual execution environments, New York, 2011.

[20] J. Ming, D. Xu, L. Wang and D. Wu, “LOOP: Logic-Oriented Opaque

Predicate Detection in Obfuscated Binary Code,” in CCS '15 Proceedings of the 22nd ACM SIGSAC Conference on Computer and Communications Security, 2015.

[21] H. Guo, J. Pang, Y. Zhang, F. Yue and R. Zhao, “HERO: A novel malware

detection framework based on binary translation,” in Intelligent Computing and Intelligent Systems (ICIS), Xiamen, 2010.

[22] H. Guan, E. Zhu, H. Wang, R. Ma, Y. Yang and B. Wang, “SINOF: A dynamic-static combined framework for dynamic binary translation,” Journal of Systems Architecture, vol. 58, no. 8, pp. 305-317, 2012.

[23] M. Braun, M. Buchwald and A. Zwinkau, “FIRM: A Graph-Based


(14)

1

BAB I

PENDAHULUAN

I.1 Latar Belakang Masalah

Self-Modifying Code berperan penting dalam pengembangan perangkat lunak komersil terutama pada kasus proteksi lisensi dari pembajakan dan malicious software dalam menyembunyikan eksistensinya. SMC juga sering dikombinasikan dengan teknik anti-debugging lainnya seperti obfuscation. Hal tersebut menjadi tantangan pada dunia reverse engineering karena sulit dianalis secara statis. Aplikasi debugger umumnya hanya mengontrol data tetap pada program dan memori saja. Salah satu menyiasatinya adalah dengan mendampingi debugger dengan metode instrumentasi. Instrumentasi pada pemograman digunakan untuk beberapa tujuan seperti hasil penggunaan memori, statistik performansi maupun pengecekan bug dari segi kegunaan dan keamananan.

Instrumentasi beroperasi dengan menanamkan kode monitoring ke dalam spesifik komponen program pada level sumber kode maupun biner. Pada kasus program Self-Modifying Code terdapat pola subtitusi fungsi yang membuat proses monitoring lepas dari pemindaian. Hal tersebut merupakan kelemahan dari instrumentasi statis yang bekerja sebelum program dijalankan atau hanya memindai binernya saja. Dengan kata lain subtitusi fungsi tidak dapat diketahui karena terjadi pada saat eksekusi program. Kesulitan lain yang akan dihadapi oleh reverse engineer adalah waktu yang diperlukan untuk memecahkan subtitusi tersebut dan akan selalu berganti setiap kali ditemukan polanya, maka dari itu perubahan harus dapat ditebak akan seperti apa selanjutnya.

Berdasarkan kendala tersebut diperlukan suatu analisis secara dinamis pada saat program ditahap runtime. Dengan menggunakan metode Dynamic Binary Instrumentation diharapkan dapat menganalisis Self-Modifying Code saat program sedang memodifikasi dirinya. Instrumentasi dinamis pada biner juga menjaga integritas biner sehingga instruksi program tetap utuh atau tidak menganggu


(15)

proses subtitusi fungsi dari Self-modifying Code itu sendiri. Proses DBI dilakukan hampir tanpa interaksi reverse engineer atau menganalisis secara otomatis, dengan begitu kasus dapat cepat diselesaikan.

I.2 Perumusan Masalah

Berdasarkan permasalahan yang telah dikemukakan pada latar belakang dapat dirumuskan, kesulitan melakukan reverse engineering terhadap program Self-Modifying Code sebagai usaha anti debugging.

I.3 Maksud dan Tujuan Penelitian

Maksud dari penelitian ini adalah menganalisis teknik Self-Modifying Code menggunakan metode DBI(Dynamic Binary Instrumentation).

Adapun tujuan yang akan dicapai dalam penelitian ini adalah memperoleh hasil analisis Self-Modifying Code yang mudah dimengerti dengan keluaran intermediate representation untuk mempermudah reverse engineer dalam menilai tindak lanjut pada proses debugging.

I.4 Batasan Masalah

Batasan masalah yang digunakan untuk Dynamic Binary Instrumentation adalah sebagai berikut:

1. Dynamic Binary Instrumentation menggunakan Open Source Framework DynamoRIO.

2. DynamoRIO digunakan dengan integrasi API (Application Programming Interface) LLVM untuk memperoleh keluaran intermediate representation

3. DynamoRIO plugin yang dibangun bertujuan memberikan nasihat atas pola Self-Modifying Code

4. DynamoRIO plugin yang dibangun bukan sebagai patcher atau mengubah program Self-Modifying Code menjadi non-Self-Modifying Code

5. DynamoRIO plugin dibangun menggunakan bahasa pemograman C++ sebagaimana API yang disediakan oleh DynamoRIO


(16)

Sedangkan batasan masalah pada kasus Self-Modifying Code terdiri dari:

1. Program Self-Modifying Code berformat ELF (Executable and Linkable Format)

2. Program Self-Modifying Code mempunyai instruksi arsitektur x86_64 atau AMD64(little endian)

3. Program Self-Modifying Code dianalisis dengan metode Dynamic Binary Instrumentation

4. Program Self-Modifying Code dianalisis dengan tujuan menemukan set instruksi pengganti dengan mudah

5. Program Self-Modifying Code bukan kompilasi JIT(Just-in-Time)

I.5 Metodologi Penelitian

Metodologi yang digunakan dalam penelitian ini adalah metode eksperimental karena dilakukan pengujian berulang – ulang dan kasus dapat diuji dengan metode lainnya. Adapun untuk analisis permasalahan digunakan metode DBI(Dynamic Binary Instrumentation).

1. Metode Pengumpulan Data a. Metode Studi Pustaka

Mencari literatur yang terkait dengan Self-Modifying Code dan Dynamic Binary Instrumentation.

b. Metode Wawancara

Berupa tanya jawab dengan reverse engineer melalui e-mail dan forum online. Metode ini digunakan untuk mendapat data – data pada sistem. 2. Metode Analisis Dynamic Binary Instrumentation

Metode yang digunakan dalam penelitian ini adalah DBI(Dynamic Binary Instrumentation) dengan menggunakan framework dari DynamoRIO. DynamoRIO beroperasi dengan menggeser eksekusi sebuah aplikasi dari petunjuk aslinya ke sebuah cache code, dimana instruksi dapat bebas dimodifikasi. DynamoRIO


(17)

menempati ruang alamat aplikasi tersebut dan memiliki kendali penuh atas eksekusi, mengambil alih setiap kali kontrol meninggalkan cache code atau ketika sistem operasi langsung mentransfer kontrol ke aplikasi (kernel-mediated control transfers).

Gambar I.1 Proses DynamoRIO

DynamoRIO menyalin kode aplikasi satu blok dasar dinamis setiap waktu ke dalam kode cache blok dasarnya. Sebuah blok yang langsung menargetkan blok lain sudah ditempati dalam cache yang terkait blok tersebut untuk menghindari kembali ke dispatcher. Urutan eksekusi dari blok dasar yang sering muncul digabungkan menjadi traces yang ditempatkan secara terpisah. DynamoRIO membuat traces tersebut tersedia melalui antarmuka untuk kemudahan akses ke kode stream.


(18)

I.6 Sistematika Penulisan

Sistematika penulisan ini disusun untuk memberikan gambaran umum tentang penelitian yang dijalankan. Sistematika penulisan penelitian ini adalah sebagai berikut:

BAB I PENDAHULUAN

Menguraikan tentang latar belakang permasalahan, mencoba merumuskan inti permasalahan yang dihadapi, menentukan tujuan dan kegunaan penelitian, yang kemudian diikuti dengan pembatasan masalah, asumsi, serta sistematika penulisan.

BAB II. TINJAUAN PUSTAKA

Membahas berbagai konsep dasar dan teori-teori yang berkaitan dengan topik penelitian yang dilakukan dan hal-hal yang berguna dalam proses analisis permasalahan serta tinjauan terhadap penelitian-penelitian serupa yang telah pernah dilakukan sebelumnya termasuk sintesisnya.

BAB III. ANALISIS SELF-MODIFYING CODE DAN PERANCANGAN DYNAMIC BINARY INSTRUMENTATION

Bab ini berisi tentang analisis masalah, analisis biner program, analisis non-fungsionalitas serta analisis perancangan metode yang digunakan. Selain itu pada bab ini memaparkan perancangan sistem yang akan dianalisis.

BAB IV. IMPLEMENTASI DAN PENGUJIAN SISTEM

Bab ini menerangkan tentang pengujian sistem berdasarkan pada metode yang digunakan dengan menggunakan unit testing dan menjelaskan apakah sudah benar-benar sesuai dengan analisis dan perancangan yang telah dilakukan.

BAB V. KESIMPULAN DAN SARAN


(19)

(20)

7

BAB II

TINJAUAN PUSTAKA

II.1 Debugging

Bug pada perangkat lunak merupakan sebuah kesalahan dalam program atau sistem yang menyebabkan setidaknya satu fungsional atau non-fungsional menjadi terganggu. Debugging adalah sebuah proses sistematis memerika program dari bug. Debugging sendiri diambil dari kata bug yang fokus utamanya memang untuk melepas bug. Namun, tujuan akhirnya tidak selalu untuk memperbaiki program, beberapa reverse engineer melakukannya agar dapat mengambil keuntungan tertentu seperti eksploitasi.

Pada umumnya debugging adalah bagaimana menciptakan suatu masalah seperti input diluar ekspektasi atau dengan membuat test case sembarangan (black box testing) sampai menimbulkan crash. Setelah program mencapai keadaan crash kemudian debugger mengeksaminasi status program dimana terjadi urutan letak masalah atau dikenal sebagai call stack. Beberapa call stack memiliki informasi yang kurang jelas atau implisit tergantung dari tingkatan kompleksnya sebuah program.

II.2 Macam-Macam Format Debugging

Format Debugging merupakan desain data yang tersimpan dalam program untuk mempermudah debugger dalam menganalisis. Macam – macam format debugging diantaranya:

1. STAB (symbol table) menyimpan informasi debug ke bagian simbolis file objek yang umumnya digunakan oleh executable pada sistem operasi UNIX terdahulu dan digunakan hingga sekarang untuk alasan kompabilitas.

2. DWARF (debug with arbitrary record format) menggunakan file objek untuk menyimpan informasi debug dengan struktur pohon di mana setiap simpul mewakili tipe data, variabel atau fungsi. DWARF menjadi standar hampir untuk semua compiler.


(21)

II.3 Instrumentation

Instrumentasi dalam istilah pemograman adalah tindakan menanamkan kode monitoring ke dalam sistem perangkat lunak. Instrumentasi dapat dilakukan dengan cara transformasi biner program, manipulasi link-time, hooks khusus dalam virtual machine(bahasa pemograman tingkat tinggi/interpreter) atau dengan transformasi pada sumber kode. Keluaran yang dihasilkan berupa peristiwa yang terjadi pada program dalam konteks spesifik, tidak meluas atau hanya bergantung pada komponen dan fungsi yang ditinjau.

Kelemahan instrumentasi terletak pada jangkauannya yang mengurucut ke fungsi target sehingga memungkinkan kode yang di-instrument lepas dari eksamen atau tidak sampai mencapai poin eksekusi ketika fungsi tersebut memanggil fungsi lainnya. Instrumentor juga berperan menggapai memori yang diakuisisi program dan membuat kinerja program menjadi lamban atau bahkan crash. Hal tersebut sangat bergantung pada kondisi environment atau resource yang dimiliki.

Dalam menentukan instrumentasi apa yang cocok untuk digunakan perlu dilihat ketersediaan informasi program. Adapun kategori tersebut dikategorikan berdasarkan language agnostic yakni:

1. DLL(Dynamic Link Library) Rewriting

Instrumentasi dijalankan saat setelah siklus kompilasi/linking dimana penggunaan hasil cache merupakan DLL yang telah dimodifikasi

2. In Place Instrumentation

Sama dengan DLL rewriting akan tetapi DLL tidak dimodifikasi begitu juga dengan target program. Fungsi – fungsi di-hook tepat untuk tugas yang diperlukan ketika DLL tersebut dimuat atau di-load pertama kali saat startup atau setelah panggilan LoadLibrary


(22)

Mirip dengan in place instrumentation tetapi hanya menginstrumentasi sebuah fungsi saat pertama kali fungsi tersebut dieksekusi

4. Intermediate Language Instrumentation

Instrumentasi pada bahasa tingkat menengah adalah memonitor aktivitas eksekusi sebelum bahasa tingkat menengah dikompilasi ke dalam instruksi executable oleh virtual machine atatu interpreter

5. Intermediate Language Instrumentation via Reflection

Java dan .Net keduanya memberikan API refleksi yang memungkinkan penemuan metadata tentang metode. Dengan menggunakan data tersebut dapat dibuat metode baru dengan on-the-fly instrumentation yang ada seperti dengan instrumentasi bahasa tingkat menengah disebutkan sebelumnya.

6. Compile Time Instrumentation

Teknik ini digunakan pada waktu kompilasi untuk menyisipkan instruksi yang tepat ke dalam aplikasi selama kompilasi. Kelemahannya membutuhkan usaha pembangunan linking yang besar.

7. Source Code Instrumentation

Teknik ini digunakan untuk memodifikasi kode sumber dengan menyisipkan kode instrumentasi yang sesuai dengan dekorator sebelum masing-masing fungsi. 8. Link Time Instrumentation

Teknik ini sangat berguna ketika dibutuhkannya penggantian memory allocators seperti fungsi realloc dengan tracing allocators. Hal tersebut berkaitan dengan pencarian bug pada memori seperti buffer overflow atau memory leak 9. IAT Hooking Instrumentation

Instrumentasi ini melibatkan modifikasi import address table untuk fungsi terkait dalam DLL atau Unix shared object. Hanya dengan patch lokasi import table dengan fungsi instrumentasi kemudian memanggil fungsi asli dari hook.


(23)

II.4 Metode Binary Instrumentation

Binary Instrumentation merupakan proses memodifikasi instruksi sebuah program ketika eksekusi. Modifikasi tersebut dapat diaplikasikan pada file executable, file objek maupun file kelas pada semua fase seperti waktu kompilasi, linking pustaka, load time atau run-time. Dynamic Instrumentation beroperasi dengan menanamkan kode dinamis ke dalam program tanpa harus rekompilasi. Dynamic Binary Instrumentation dapat menganalisis eksekusi program secara step-by-step pada konteks memori dan register dan hanya menganalisis kode yang dieksekusi.

Dynamic Binary Instrumentation adalah sebuah metode analisis tingkah laku aplikasi secara runtime pada saat eksekusi melalui penanaman kode instrumentasi. Kode intrumentasi tersebut mengeksekusi sebagai bagian dari instruksi asli. DBI dibagi atas dua berdasarkan cara kerjanya yaitu light-weight dan heavy-weight. Light-weight DBI beroperasi pada instruksi stream secara spesifik berdasarkan arsitektur dan status perlakuan analisis sedangkan heavy-weight beroperasi secara abstrak pada stream dan status instruksinya [2].

Berbeda dengan Static Binary Instrumentation yang memodifikasi file executable maupun pustakanya dengan pendekatan sebelum eksekusi program. Instrumentasi biner dinamis memanipulasi saat program di tahap sudah dimuat dalam memori. Instrumentasi biner secara statis mempunyai keunggulan dalam hal performansi karena DBI melakukan penyisipan sebelum eksekusiyang berakibat akses informasi seperti nama variabel menjadi sulit.

II.5 ELF

ELF (Executable and Linking Format) ialah format file executable standar UNIX System V seperti Linux yang dibagi beberapa seksi seperti .text untuk kode, .data untuk variabel global, .rodata yang umumnya menyimpan strings konstan, .bss(Block Started by Symbol) data segment yang mengandung variabel statis representasi oleh zero-valued(pengosongan memori) ketika eksekusi dimulai dan .stab untuk simbol debugging. File ELF juga berisi header yang menggambarkan bagaimana seksi tersebut harus disimpan dalam memori.


(24)

Gambar II.1 ELF Diagram

ELF dahulunya disebut Extensible Linking Format karena dapat direlokasi dengan mudah mengandalkan linking dan loading DSO (dynamically linked shared objects). Namun, ELF juga mampu mendukung position independent code yang menghindari pengalamatan secara absolut atau tidak membutuhkan relokasi sama sekali. Hal tersebut berbeda dengan pustaka statis walaupun ELF juga mendukung sistem portable.

II.6 Self-Modifying Code

Self-Modifying Code adalah sebuah teknik pemograman dimana program dapat merubah fungsi dengan sendirinya ketika eksekusi. Teknik tersebut


(25)

merupakan cetusan dari Rice’s theorem dimana untuk setiap properti non-trivial dari fungsi parsial, tidak ada metode umum dan efektif yang dapat memutuskan apakah suatu algoritma mengkalkulasi fungsi parsial properti tersebut. Logika Self-Modifying Code pada dasarnya menggunakan ekspresi lambda kalkulus dalam subtitusi fungsi.

Self-Modifying Code kerap kali diidentikkan dengan salah satu teknik obfuscation namun, program tidak serta merta menjadi kompleks dalam hal analisis melainkan performa program yang membaik dan baris kode yang lebih efisien. Rata – rata program obfuscated adalah memberikan junk yang tidak berarti untuk mengelabui analis sedangkan Self-Modifying Code umumnya mengambil jalan potong untuk instruksi yang lebih sederhana.

Berdasarkan fungsinya Self-Modifying Code dibagi atas beberapa tujuan. Adapun contoh diantaranya yang sering digunakan adalah sebagai berikut:

1. Self-Checksumming

Program melakukan pengecekan integritas terhadap variasi segmen kode saat eksekusi untuk memastikan bahwa biner program tidak diubah. Verifikasi berada pada segmen memori dengan status segmentation fault atau program dihentikan dengan signal handler interupsi tertentu jika terdeteksi ketidaksesuaian. Hal ini bukan mengecek apakah hash checksum dari keseluruhan biner berbeda melainkan keutuhan dari instruksi program. Adapun contoh dari Self-Checksum dapat dilihat pada pseudocode assembly berikut:

add (rbx), r15 ;membaca memori

sub 1, ecx ;looping counter secara decrement add rdi, rax

xor r14, rdi add rcx, rdx add rbx, rdi

xor rax, rdx ;modifikasi register jump_target yaitu rdx dan rdi xor r15, rdi


(26)

add rdi, r14 ;modifikasi checksum dengan rdx dan rdi xor rdx, -8(rsp) ;modifikasi checksum dalam stack xor r15, r13

add r14, r12 rol r15

xor rdi, rbx ;membuat pseudorandom akses memori and mask1, ebx

or mask2, rbx xor rdx, rsp and mask3, esp or mask4, rsp

and 0x180, edx ;Modifikasi penunjuk stack dan alamat target_jump and 0x1, rdi

add rdi, rdx add rdi, rdi add rdi, rdx

or mask, rdx ;membuat alamat target_jump

xor rdx, r15 ;Menambahkan alamat target_jump ke dalam checksum mov rax, rdi

imul rax, rax or 0x5, rax pushfq

add (rsp), rbx

jmp *rdx ;jump ke 1 dari 4 blok

2. Self-Decrypting

Enkripsi dapat diimplementasikan pada biner executable dan didekripsi pada saat program dijalankan. Biasanya menggunakan instruksi aritmetik XOR(exclusive-or) maupun polymorphic dengan menambahkan operasi bit instruksi ADD(addition) dan SUB(subtraction). Contoh Self-Decrypt dapat dilihat pada pseudocode assembly berikut:

main:

pop rsi ; pop alamat data


(27)

dienkripsi decode:

mov al, byte [rsi] ; Muat karakter dari kunci ke al

xor byte [rsi+38], al ; xor kunci dengan kode yang dienkripsi

inc rsi ; increment alamat dekode loop jmp rsi ; jump ke kode yang didekripsi

3. Self-Extracting

Biner executable dapat diperkecil ukuran datanya dengan teknik kompresi yang kemudian diekstrak ke memori untuk mendapatkan fungsi program sebenarnya. Algoritma kompresi yang digunakan sama dengan metode untuk kompresi file seperti Huffman/Lempel-Ziv, Welch, Lempel-Ziv-Markov dan PAQ akan tetapi header atau magic program tetap sebagaimana executable semestinya. Berikut contoh self-extract dalam bahasa pemograman assembly:

inject_loop:

cmpb $0x20, (%rax, %rsi, 1) je inject_finished

movb (%rax, %rsi, 1), %r10b xor $0x3, %r10b

movb %r10b, (%rcx, %rsi, 1) inc %rsi

jmp inject_loop

inject_finished: inc %rsi

movb $0xc3, (%rcx, %rsi, 1) push %rdi

push %rcx ret


(28)

4. Self-Repairing

Self-Error-Correcting atau Self-Healing code merupakan upaya untuk memperbaiki perangkat lunak dari error dengan sendirinya agar tidak pernah crash. Hal ini merupakan topik lanjutan dari SMC karena menggunakan kecerdasan buatan dalam implementasinya. Konsep dari Self-Repairing adalah menyalin instruksi clean untuk memperbaiki jika ada satu atau lebih instruksinya rusak. Adapun contohnya dapat dilihat pada pseudocode assembly berikut yang merupakan safepoint pada hardisk atau S.M.A.R.T. (Self-Monitoring, Analysis and Reporting Technology)

disk:

movb cl, (si) ; Jumlah sektor yang akan dibaca

push si ; Simpan si

mov si, #LOADOFF+ext_rw ;

movb 2(si), cl ; Mengisi blok yang akan ditransfer

mov 4(si), bx ; alamat buffer

mov 8(si), ax ; Memulai angka blok

mov 10(si), dx

movb dl, device(bp) ; dl = device yang akan dibaca

movb ah, #0x42

int 0x13

pop si ; Mengeluarkan si ke poin alamat array

!jmp rdeval rdeval:

jc error ; Jump ke disk yang error dibaca

movb al, cl addb bh, al addb bh, al

add 1(si), ax ; Pembaharuan alamat oleh sector baca

adcb 3(si), ah

subb (si), al ; Decrement jumlah sektor dengan sector

baca

jnz load ;

add si, #4 ; memperbaiki alamat selanjutnya


(29)

yang dibaca

jnz load ; Baca instruksi selanjutnya

5. Self-Testing

Self-Testing Code bertujuan me-refactoring kode agar dapat menguji testcase dengan sendirinya. Pendekatan ini mirip dengan built-in test akan tetapi eksekusi bersifat jika peristiwa tertentu terjadi seperti kegagalan fungsi progam (bug) dalam menjalankan tugasnya. Adapun contohnya dapat dilihat pada pseudocode berikut:

MOV R1, 00000000 ; R1 = 0 MOV R2, 00000000 ; R2 = 0 MOV R6, 00000000 ; R6 = 0

MOV R7, signature ; deklarasi signature MOV R8, 11111111 ; 4-bit increment dengan 1 loop: UMUL R4,R3,R2,R1 ; multiplikasi

ADD R5,R4,R3 ; tambah words ADD R6,R6,R5

ADC R6,R6,0

ADD R2,R2,R8 ; increment R2 CMP R2, 11111110

BNE loop

MOV R2, 00000000 ; R2 = 0 ADD R1,R1,R8 ; increment R1 CMP R1, 11111110

BNE loop

CMP R6,R7 ; cek signature BNE test_fail_routine JMP test_pass_routine

II.7 Anti Debugging

Anti-debugging adalah salah satu upaya untuk menghambat reverse engineering sehingga analis tidak dapat menggunakan debugger untuk menganalisis program. Teknik ini umum digunakan untuk mencegah pembajakan


(30)

perangkat lunak dan infeksi dari program lain seperti malware (malicious software). Pada dasarnya semua sistem proteksi software primitif dibagi atas dua ide yaitu checks dan landmines. Checks menghasilkan nilai ubahan atau jalan eksekusi kode berbasis status item yang dicek sedangkan landmines seperti crash, hang, scramble yang menginterupsi alat analisis atau debugger itu sendiri.

Beberapa bahasa pemograman telah menyediakan fungsi built-in berupa API (Application Programming Interface) untuk pendeteksian debugger dan virtual machine. Selanjutnya programmer dapat memutuskan apakah debugger diizinkan untuk menganalisis atau tidak. Anti-debugging juga dapat diciptakan oleh compiler yang fungsinya menghapus readable strings (metadata) termasuk informasi debug atau dengan memberikan obfuscation agar instruksi program menjadi kompleks.

II.8 DynamoRIO

DynamoRIO adalah salah satu framework atau alat Dynamic Binary Instrumentation yang tersedia multiplatform dan sumber terbuka. Alat tersebut merupakan kombinasi dari Dynamo, sebuah mesin optimasi dinamis yang dikembangkan oleh peniliti dari HP dan RIO yaitu runtime instropection and optimization engine yang dikembangkan oleh MIT. DynamoRIO mendukung analisis aplikasi pada sistem operasi seperti Windows, Linux dan OSX yang mempunyai arsitektur x86, AMD64 dan ARM.

Salah satu kelebihan DynamoRIO adalah analisis sudut pandangnya yang menanamkan kode instrumentasi ketika binary fragment sedang dimasukkan ke dalam fragment cache. Hal tersebut sangat berguna untuk mencegat akses memori di dalam aplikasi. Ketika fragmen sedang dibuat, pustaka analisis DynamoRIO berperan masuk ke instruksi dalam fragmen yang dihasilkan. Menggunakan pengetahuan tersebut memungkinkan analis merancang pustaka analisis yang dapat mencegat memori dalam membaca dan menulis ketika aplikasi dieksekusi.

Performansi merupakan kendala besar dalam instrumentasi biner dinamis. PIN yang merupakan perangkat lunak DBI dari Intel kurang unggul dalam hal


(31)

performansi karena menggunakan rekompilasi JIT(Just-in-Time) terhadap seksi kode yang memerlukan kerja ekstra. Namun untuk mengatasi logika kompleks DynamoRIO dirasa tidak mumpuni karena ketersediaan pada kode cache terbatas. Berikut ini dapat dilihat benchmark dalam analisis perangkat lunak chromium yang menggunakan beberapa pustaka seperti kriptografi hingga multimedia

Gambar II.2 DynamoRIO Benchmark

PIN berulang kali melakukan iterasi untuk memastikan instruksi yang kompleks benar-benar valid. Sedangkan Inference DynamoRIO yang merupakan modifikasi khusus untuk target program hanya memerlukan informasi sederhana dari arus instruksi berjalannya sebuah program karena informasi lainnya sudah terdapat pada pustaka analisis yang dibuat.

II.9 Profiling

Profiling dalam informasi teknologi adalah aktivitas mengumpulkan informasi penggunaan resources dan waktu yang diperlukan untuk menjalankan suatu aplikasi. Profiling umumnya bertujuan untuk menemukan apa yang menyebabkan performansi aplikasi menjadi lamban. Keluaran yang dihasilkan


(32)

dapat berupa penggunaan instruksi, panggilan fungsi diikuti waktu eksekusi hingga aplikasi berhenti dalam bentuk teks maupun visualisasi grafik. Profiling dapat dilakukan dengan kode instrumentasi yang ditanam pada biner program atau pada level kode sumber.

Peristiwa yang terjadi pada program dapat diukur dengan statistik atau benchmarks. Dengan memberikan kerja berat pada aplikasi, benchmarking lebih memberikan informasi maksimal. Variasi kondisi membuat benchmarking dan profiling menjadi dua hal yang berbeda. Aktivitas profiling pada dasarnya tidak dibebani tugas yang berat melainkan tingkah laku pada status normal.

II.10 Tracing

Tracing dalam istilah pemograman merupakan salah satu teknik debugging yang digunakan untuk memahami proses berjalannya sebuah program. Tracing sering kali dikomparasikan dengan logging karena berupa catatan seperti file apa saja yang dibuka, pustaka apa saja yang dipanggil dan sebagainya. Terdapat beberapa level dalam mekanisme trace yaitu Verbose, Debug, Info, Warning, Error, Fatal dan Silent. Buffer yang ditampilkan juga melingkupi bagian Main, System, Radio, Events bahkan Crash.

Keluaran trace paling popular adalah backtrace atau stacktrace dimana beberapa stack frame yang menjadi masalah pada program dikembalikan sampai ke pangkal fungsi utama aplikasi. Stacktrace pada bahasa pemograman tingkat tinggi di-handle oleh interpreter dan berisi poin baris kode yang menginterpretasikan referensi masalah sedangkan, bahasa tingkat rendah memerlukan simbol debug atau jika tidak ada, keluaran berupa bahasa mesin atau assembly.

II.11 Binary Analysis

Analisis biner adalah sebuah pendekatan membongkar program dengan disassembly atau dekompilasi untuk tujuan reverse engineering. Pekerjaan ini dilakukan ketika analis tidak memiliki sumber kode. Aktivitas analisis biner meliputi hex editing hingga membuat flow- graph. Beberapa alat analisis biner


(33)

mendukung terjemahan yang sederhana ke dalam byte code atau emulasi sebagai binary translation. Hal tersebut berkenaan bahasa mesin atau assembly sulit dimengerti terutama pada aplikasi berskala besar yang mempunyai jutaan instruksi.

Biner program juga dapat direpresentasikan dalam bahasa tingkat menengah namun, bahasa tersebut sangat independen tergantung compiler yang mengkompilasinya. Alat analisis biner berperan langsung dalam dekompilasi ke bahasa independen tersebut. Analisis biner juga dapat dilakukan secara dinamis dengan mengeksekusi program pada real dan virtual processor. Terminologi analisis biner sangat dekat dengan runtime analysis karena keterbatasan analisis statis yang tidak mumpuni untuk perangkat lunak berproteksi.

II.12 Program Lifecycle Phase

Fase umum dari hidupnya sebuah perangkat lunak dari sumber kode hingga menjadi biner yang dijalankan meliputi:

II.12.1 Edit Time

Edit time adalah fase dimana ketika kode program sedang diubah artinya status program bisa jadi belum ditahap konsisten. Perubahan biasanya dilakukan oleh programmer namun, dapat pula dilakukan oleh generator, alat desain atau dengan sistem meta-programming. Contohnya seperti pengecekan syntax atau analisis sumber kode maupun merubah bahasa pemograman satu ke yang lainnya. II.12.2 Compile Time

Compile time adalah fase setelah sumber kode diterjemahkan kedalam bahasa mesin oleh compiler. Pada tahap kompilasi terjadi pengecekan atas konsistensi kode yang diubah dan menghasilkan sebuah file executable. Untuk bahasa pemograman tingkat tinggi yang menggunakan interpreter, kompilasi berupa merubah sumber kode menjadi bytecode.

II.12.3 Link Time

Link time adalah fase menghubungkan pustaka dengan program yang menginvokasinya. Koneksi tersebut dapat diikat secara statis maupun dinamis


(34)

atau bahkan ketika eksekusi. Linking kerap kali dikaitkan dengan kompilasi walaupun sebenarnya tahap ini terpisah. Linking juga merupakan penggabungan beberapa file objek menjadi satu buah executable.

II.12.4 Load Time

Load time adalah fase ketika file executable dipanggil dan ditempatkan dalam memori yang aktif sebagai bagian dari mulainya eksekusi. Sederhanya adalah tahap dimana program pertama kali dijalankan yang mana sudah tidak lagi berupa file melainkan menjadi kesatuan atau pengalamatan interface pada kernel. II.12.5 Run Time

Run time adalah fase dimana program sedang berjalan normal maupun tidak normal seperti hang. Di tahap ini program berada di status sudah mengakuisisi memori dan dapat mulai bekerja secara multi threading atau menciptakan proses child.

II.13 Binary Translation

Binary Translation adalah proses menerjemahkan kode mesin (biner) dari satu set instruksi ke instruksi lainnya. Sistem yang menggunakan hal tersebut direferensikan sebagai emulator. Kebanyakan Binary Translation mempunyai fungsi alat migrasi untuk transisi arsitektur lama ke yang baru. Penerjamahan biner dapat dilakukan secara statis (seluruh biner ke target platform) maupun dinamis dengan menerjemahkan kode saat eksekusi secara parsial berdasarkan fungsi yang diinginkan [3].

Beberapa Dynamic Binary Translation menggunakan “fast return” atau indirect branch/call prediction dalam pendekatan mengindari overhead. Pada processors terbaru prediksi menggunakan dua level adaptif predictor. Instruksi tersebut berkontribusi lebih dari satu bit ke history buffer. Prosesor tanpa mekanisme tersebut secara sederhana memprediksi sebuah indirect jump ke lokasi yang sama terakhir kalinya. Contoh sederhana implementasi dari Binary Translation dapat ditemukan pada mesin virtualisasi seperti Qemu atau VMware.


(35)

II.14 Intermediate Representation

IR atau sering disebut bahasa tingkat menengah merupakan representasi program diantara sumber kode dan biner (assembly). Hal tersebut sangat independen tergantung pada compiler maupun interpreter-nya. Representasi dapat digambarkan melalui graph seperti AST (Abstract Syntax Tree) maupun biner dalam bytecode. Bytecode mempunyai tujuan retargetable untuk merekonstruksi kembali kedalam biner. Pada dasarnya IR memiliki contoh padanan menampilkan algortitma sebagai berikut:

if (x + 2 > 5) y = 2;

else y = 3; x++;

t = x + 2

if t > 5 goto l1 y = 3

goto l2 l1: y = 2 l2: x = x + 1

II.15 Reverse Engineer

Reverse engineer dalam dunia komputer adalah orang yang mempunyai tugas merekayasa hasil objek baik perangkat keras maupun lunak untuk mengubah atau mengembalikkan informasi sumbernya. Pada biner aktivitasnya meliputi membaca kode mesin assembly untuk program executable dan membaca hexademical untuk objek lainnya seperti gambar atau video yang kemudian direplikasi atau patching menjadi sesuai keinginan reverse engineer.

Terdapat bermacam-macam teknik reverse engineering untuk perangkat lunak diantaranya melakukan analisis secara statis(disassembly) langsung pada biner program hingga memasukkanya dalam ruang lingkup debugger. Beberapa reverse engineer melakukan instrumentasi atau menyisipkan program bantuan untuk melakukan analisis secara otomatis dan bermain di area memori. Untuk reverse engineer yang tidak biasa dengan hal tersebut biasanya menggunakan intermediate representation sebagai acuan dalam mengolah data yang menjadi optimasi.


(36)

23

BAB III

ANALISIS SELF-MODIFYING CODE DAN PERANCANGAN

DYNAMIC BINARY INSTRUMENTATION

III.1 Analisis Sistem

Subbab analisis ini membahas mengenai analisis masalah, analisis biner program, analisis kebutuhan nun fungsional, analisis teknik Self-Modifying Code dan perancangan Dynamic Binary Instrumentation.

III.1.1 Analisis Masalah

Masalah yang menjadi latar belakang pada penelitian ini adalah bagaimana menganalisis Self-Modifying Code setelah dikompilasi ke dalam biner program untuk memahami cara kerjanya menggunakan metode DBI(Dynamic Binary Instrumentation). Adapun spesifikasi masalah adalah pengaruh Self-Modifying Code sebagai usaha anti analisis dalam membuat proses debugging menjadi sulit, kendala Dynamic Binary Instrumentation dalam menganalisis program serta konfigurasi environment yang berbeda-beda.

III.1.2 Analisis Biner Program

Analisis Biner adalah proses menganalisis dan menggambarkan bagaimana program dalam bekerja menjalankan tugasnya. Teknik analisis biner memiliki ruang lingkup yang luas. Selain meliputi biner yang melibatkan sistem operasi, analisis biner juga memodelkan aspek–aspek yang terkait dengan instruksi independen arsitektur. Instruksi yang perlu diketahui untuk menganalisis program Self-Modifying Code adalah transfer kontrol tidak kondisional seperti:

Tabel III.1 Transfer Kontrol

Instruksi Keterangan

JMP JMP(Jump) adalah transfer kontrol satu arah dan tidak menyimpan alamat kembali di stack


(37)

CALL CALL(Call Procedure) mendorong alamat kembali ke stack dan transfer kontrol ke prosedur

RET RET(Return From Procedure) memunculkan alamat kembali dari stack dan mengembalikan kontrol ke lokasi tersebut

Tidak ada urutan standar dalam analisis biner karena setiap proses debugging adalah seni. Adapun langkah-langkah yang diambil untuk analisis biner Self-Modifying Code dengan Dynamic Binary Instrumentation adalah sebagai berikut:

1. Memeriksa fungsi de-obfuscation routine dengan disassembly secara statis. Hal ini dapat dilakukan dengan alat seperti objdump maupun debugger seperti GDB.

2. Setelah mengetahui fungsi dimana terjadi Self-Modifying Code, dilakukan pembangunan instrumentasi untuk memonitoring fungsi tersebut.

3. Selanjutnya program Self-Modifying Code dijalankan dengan invokasi instrumentor dalam hal ini DynamoRIO

4. Setelah hasil analisis berupa keluaran intermediate reprsesentation dilanjutkan dengan membuat script sederhana atau patcher untuk memecahkan Self-Modifying Code tersebut

5. Membuat laporan cara kerja dengan teliti apa yang sebenarnya dilakukan oleh kesuluruhan program

III.1.3 Analisis Teknik Self-Modifying

Self-Modifying Code yang dianalisis merupakan perspektif telah menjadi program executable artinya tidak ada akses untuk sumber kode. Informasi yang tersedia hanya kode assembly pada biner dimana setiap routine harus diidentifikasi terlebih dahulu untuk mendapatkan fungsi yang mengolah modifikasi. Terdapat tiga kasus yang akan diuji diantara lain Self-Checksumming, Self-Decrypting dan Self-Extracting.


(38)

1. Self-Checksumming

Program Self-Modifying yang memverifikasi keaslian kode selama eksekusi terdapat sisipan produser kode perhitungan checksum. Sebuah algoritma checksum menghitung hash melewati berbagai kode kritis yang tidak boleh diubah. Verifikasi tersebut membandingkan hasil perhitungan checksum terhadap nilai yang tertera secara hard-coded dalam fungsi program. Kegagalan verifikasi menunjukkan dugaan modifikasi dari program dimana integritas tidak lagi terjamin.

Dimisalkan sebuah program yang dapat dijalankan hanya dengan adanya lisensi yang valid. Program harus dapat melindungi modifikasi kode yang melakukan cek lisensi. Reverse engineer mungkin menghapus fungsi pengecekan lisensi tersebut dengan cukup memasukkan instruksi jump pada kode dimana cek lisensi berada. Artinya pengecekan dilewati atau tidak dieksekusi sama sekali. Adapun contoh self-checking checksum dapat dilihat pada pseudocode berikut:

Selfcheck(checksum, nonce, codeStart, codeEnd,

codeSize) {

while (iteration < 2500000)

{

checksum[0] += nonce;

checksum[1] ^= DP;

checksum[2] += *DP;

checksum[4] ^= EIP;

mix(checksum);

nonce += (nonce*nonce) | 5;

DP = codeStart + (nonce %

codeSize);

iteration++;

} }

Nonce mempunyai nilai acak(integer) yang tidak pernah sama setiap kali eksekusi. Bagian codeStart, codeEnd dan codeSize didefinisikan pada seksi header program yang diperoleh ketika kompilasi.


(39)

2. Self-Decrypting

Idealnya perangkat lunak yang mendekripsi bagian dirinya hanya berisi decryptor stub (informasi yang digunakan untuk mendekripsi) dan kode yang terenkripsi. Ada banyak varian dari metode enkripsi, beberapa diantaranya cendrung statis (dengan kunci dekripsi) dan yang lainnya dengan polymorphic atau mengubah kunci dekripsi. Hal ini dilakukan dalam rangka untuk membuat ruang lingkup debugger atau emulasi pada antivirus berhenti. Adapun klasifikasi enkripsi biner dibedakan berdasarkan bagaimana kode tersebut didekripsi yaitu:

1. Dengan kunci statis (dekripsi routine sangat mudah dimengerti)

2. Kunci yang berubah-ubah sewaktu-waktu(looping dengan increment +1, mudah dimengerti namun sedikit kerja ekstra untuk reverse engineer) 3. Tanpa kunci atau hanya operasi bit (contoh instruksi circular shift atau

penggeseran seperti not, rol, ror, x-bit swap)

4. Kunci dengan eksternal dependensi(Berganti terus menerus dan tidak mempunyai pola spesifik seperti pada pengalamatan modul poin entri atau alamat virtual di memori untuk executable)

5. Tanpa kunci sama sekali(kode dekripsi didapatkan dengan brute force) Cryptanalysis dapat dilakukan dengan menggunakan metode Stream Cipher Attack atau memanfaatkan informasi yang muncul berkali-kali. Adapun kasus polymorphic self-decryption dapat dilihat pada pseudocode assembly berikut:

LEA SI,... MOV SP,0682h JUMP:

XOR WORD PTR [SI],SI XOR WORD PTR [SI],SP INC SI

DEC SP JNZ JUMP

Berdasarkan kode diatas kunci dekripsi akan berganti dengan multiple execution dikarenakan stack pointer diinilisiasi sebelum looping. Berdasarkan pengamatan dekripsi routine tersebut seharusnya kode enkripsi menggunakan


(40)

byte,word dan dword sebagai kunci atau kode metadata seperti alamat relative dan absolute pada memori sebagai kuncinya untuk enkripsi yang lebih baik.

3. Self-Extracting

Sederhananya Self-Extracting melakukan unpacking satu atau lebih segmen yang mengandung data konstan ke dalam blok yang dialokasikan pada memori executable dan kemudian memulai proses langsung melompat pada kode sebenarnya. Dengan kata lain sama seperti self-decrypting dimana terdapat decompressor dan program loaders. Self-Extracting dibangun menggunakan packers yaitu UPX(Ultimate Packer for eXecutable).

Ketika packing executable menggunakan UPX, semua seksi seperti .text dan .data dikompresi dengan penamaan UPX0, UPX1 dan seterusnya. Kemudian UPX menambahkan seksi kode diakhir yang mengandung keseluruhan dekompresi saat eksekusi. Berikut ini langkah-langkah yang dilakukan oleh UPX:

1. Eksekusi dimulai dengan OEP(Original Entry Point) baru 2. Menyimpan status register menggunakan instruksi PUSHAD 3. Semua packed atau pemadatan di-unpack dalam memori

4. Memuat kembali alamat import table orisinil dari file executable 5. Memuat kembali status register asli menggunakan instruksi POPAD 6. Terakhir jump ke OEP untuk memulai eksekusi executable sebenarnya


(41)

III.1.4 Analisis Binary Translation

Program yang emodifikasi bagian dirinya menimbulkan masalah ketika kode yang telah diterjemahkan berganti menjadi program asing. Jika binary translators tidak menyadari akan hal tersebut, binary translator akan mengeksekusi kode asal saat sebelum diterjemahkan. Analisis Binary Translation dilakukan berkenaan dengan desain keluaran yang akan dihasilkan berupa representasi bahasa pemograman tingkat menengah.

Performansi pada proses translasi biner juga patut diperhatikan. Adapun konsep yang dapat mempengaruhi proses translasi biner menjadi cepat atau bahkan lamban adalah sebagai berikut:

1. Looping Translation

Proses penerjemahan berjalan pada unit dasar blok. Sebuah blok dasar adalah aliran langsung instruksi dengan instruksi cabang (JMP, call, dll) di tail namun bukan di dalam fungsi. Sebuah blok dasar diterjemahkan dapat langsung dijalankan pada CPU. Ketika instruksi branch terakhir dijalankan, kemudian ditentukan apakah target branch sudah diterjemahkan. Jika iya, Translator hanya bisa melompat disana. Jika tidak, Translator harus menerjemahkan blok dasar pertama. Panggilan untuk mengirimkan trampolin ditambahkan ke setiap blok dasar yang diterjemahkan.

for (;;) {

if (!(translated_pc = find_translation(pc)) translated_pc = translate_basic_block(pc); execute(translated_pc);

}

2. Direct Branch

Branch langsung adalah jika target dapat ditentukan pada saat penerjemahan. Misalnya, memanggil fungsi tetap merupakan branch langsung. Jika hanya ada satu target yang deterministik untuk branch maka penerjemahan akan sangat mudah untuk dioptimalkan. Ketika menemukan sebuah branch langsung dilakukan pemeriksaan terlebih


(42)

dahulu apakah sudah dijalankan. Jika iya, binary translator dapat dengan mudah meng-encode target branch. Jika tidak, bangun trampolin seperti: push $patch_addr

push $target_pc

jmp dbt_find_direct_internal

Dimana patch_addr adalah pointer ke target branch langsung dalam instruksi branch asli. dbt_find_direct_internal adalah fungsi perakitan untuk menyimpan dan memulihkan konteks program. Ketika fungsi tersebut dipanggil selanjutnya adalah menerjemahkan blok dasar yang hilang dengan menerjemahkan translated_pc ke patch_addr. Oleh karena itu ketika instruksi branch asli ditemui kedua kalinya, langsung melompat ke target yang benar tanpa overhead.

3. Indirect Branch

Karena Branch tidak langsung tidak dapat ditentukan pada saat penerjemahan maka, diselesaikan pada saat runtime. Efektivitasnya langsung mempengaruhi kinerja sistem DBT.

4. Return Handling

Instruksi ret adalah bentuk khusus dari percabangan tidak langsung yang sangat mudah diprediksi. Beberapa sistem DBT menggunakan pendekatan "fast return" untuk meminimalkan terjadinya overhead. Ketika call dijalankan, binary translator mendorong alamat pengirim yang diterjemahkan, bukan alamat pengirim asli untuk stack. Masalah utama dari pendekatan ini adalah tidak transparan untuk aplikasi pokok, dan fitur tertentu seperti exception handling akan gagal jika alamat kembali diubah. DynamoRIO menerapkan teknik yang disebut "return cache". Kembalinya cache bermaksud tabel hash terdiri dari pemetaan dari alamat kembali. Setiap hash bucket memiliki hanya satu entri. Ketika instruksi panggilan dijalankan, pc yang diterjemahkan dari alamat pengirim ditulis ke hash table bucket. Ketika instruksi kembali dijalankan, alamat pengirim di stack diiris dan melompat masuk ke hash yang sesuai. Alamat kembali cache mungkin dapat terjadi kesalahan.


(43)

Untuk menangani kasus ini, sebuah stub sederhana ditambahkan setelah instruksi panggilan.

1. Call return pair optimization

CPU modern memiliki mekanisme prediksi branch yang maju untuk meningkatkan efisiensi eksekusi. Salah satu optimasi tersebut disebut "return stack buffer". Hal tersebut merupakan ring buffer yang mirip dengan alamat kembali cache. Ketika instruksi call dijalankan, alamat kembali dimasukkan ke buffer. Ketika instrruksi ret dijalankan, tumpukan atas muncul dan digunakan sebagai prediksi alamat target. Untuk mengambil keuntungan dari ini, instruksi call dan ret harus dalam pasangan. Dalam sistem penerjemahan biner tradisional dinamis dua instruksi tersebut biasanya diimplementasikan menggunakan instruksi jmp ke berbagai trampolin yang benar-benar hilang optimasinya dari return stack buffer.

2. CPUID Emulation

Karena setiap instruksi harus secara eksplisit diharapkan agar bekerja seluruhnya. Informasi CPUID tidak dapat ditinggalkan dari host langsung ke target aplikasi. Pertimbangan dukungan instruksi khusus seperti AVX langsung menggunakan CPUID asli yang membuat aplikasi berpikir dapat menggunakan instruksi AVX. Oleh karena itu binary translator harus mencegat instruksi CPUID dan menutupi keluar fitur tersebut.

III.1.5 Analisis Sintaksis

Parsing atau Syntatic Analysis menggunakan DCFG(Dynamic Control-Flow Graph) yang mana menambahkan data dari sebuah spesifik eksekusi program. Biasanya CFG didefinisikan secara statis dan tidak mengandung informasi tentang jalur eksekusi dari setiap beban kerja tertentu. Adapun kelebihan DCFG antara lain:

1. Sebuah DCFG berisi node awal yang tidak memiliki node pendahulu dan pengganti node-nya berisi instruksi pertama yang dieksekusi per thread. Hal ini juga berisi node akhir yang tidak memiliki node


(44)

penerus dan pendahulunya berisi instruksi terakhir yang dieksekusi per thread.

2. Setiap edge DCFG ditambah dengan jumlah yang dinamis untuk menunjukkan berapa kali dilalui per thread oleh eksekusi program yang diberikan. Kecuali untuk awal dan akhir node, hitungan dinamis setiap node adalah sama dengan jumlah dari semua edge yang masuk, yang juga sama dengan jumlah dari semua edge keluar nya.

3. Sebuah DCFG tidak perlu mengandung node atau edge yang tidak dieksekusi. Sebuah DCFG diperbolehkan mengandung node dan edge yang tidak dieksekusi atau hanya akan memiliki jumlah nol.

4. Sebuah DCFG berisi edge yang mewakili semua jalur kode eksekusi sebenarnya, bahkan untuk non-control-flow. Sebagai contoh, sebuah instruksi floating-point yang menyebabkan pengecualia selama eksekusi dapat menciptakan keunggulan untuk kode exception-handling.

Blok di DCFG dapat dikombinasikan menjadi tingkat yang lebih tinggi untuk konstruksi seperti perulangan, rutinitas dan biner images. Data dinamis seperti jumlah iterasi loop dapat disimpulkan dari jumlah edge dasar. Format DCFG memungkinkan penyimpanan informasi pada proses, termasuk images konstituen, simbol, data debug, dan kontrol.

Jenis dari elemen dideskripsikan menggunakan format JSON yang mempunyai list untuk setiap strukturnya. Hal tersebut nantinya disimpan sementara dalam memori untuk mempermudah penerjemahan biner dalam hal parsing. Adapun spesifikasinya sebagai berikut:

1. Top-level structure

Nilai dari Top-level adalah sebuah objek atau urutan pasangan nilai kunci. Bagian utama dari aliran DCFG ditandai dalam objek tingkat atas yang terdaftar secara singkat dibawah dan diperluas dalam sisa dokumen berikut ini:


(45)

1. Versi format

2. Daftar pengidentifikasi (id) digunakan untuk referensi string kemudian di-stream seperti nama file, jenis edge dan node khusus.

3. Data proses berisi id, jumlah instruksi per-thread, serta daftar images dari biner seperti alamat dan ukuran Load, daftar simbol, sumber berkas, garis nomor debug data, daftar node blok dasar, daftar rutinitas dan loop konstituen.

2. Versi

Versi mayor dan minor dari format file terdaftar sebagai dua tag terpisah di objek tingkat atas. Maksudnya adalah bahwa format DCFG akan kemabali dan maju secara kompatibel sebanyak mungkin. Kompatibilitas berarti bahwa versi ke depan tidak harus mengubah tag yang telah ditentukan atau menghapus data non-opsional. Kompatibilitas ke depan berarti bahwa penambahan harus dilakukan parser untuk format yang sudah ada harus mampu membaca format ke depan jika mengabaikan tag yang diketahui.

Jika kompatibilitas rusak, atau jika fitur baru utama ditambahkan, nomor versi utama harus bertambah dan nomor versi minor ulang ke nol. Jika tidak, perubahan format lain dibuat nomor versi minor yang bertambah. Ketika dikonversi ke teks, versi mayor dan versi minor dipisahkan oleh sebuah titik (".") dan versi minor harus ditampilkan sebagai dua digit yang memungkinkan hingga versi 99 tanpa kebingungan karena nilai tempat desimal, misalnya 2.03 mendahului 2.12.

3. Nama File

Daftar nama file yang digunakan untuk menghemat ruang adalah dengan mengizinkan nama file direferensikan nanti oleh pengidentifikasi bilangan bulat, bukan string panjang yang mungkin perlu diulang berkali-kali. Adapun yang harus diperhatikan untuk nama file adalah:


(46)

1. Seperti layaknya semua string, karakter khusus harus lolos memenuhi format string JSON.

2. Parsers tidak boleh berasumsi bahwa id mulai dengan satu atau berurutan dalam pemesanan tertentu.

3. Semua nama file yang digunakan dalam aliran DCFG disimpan dalam tabel yang sama, termasuk untuk images dan file sumber.

4. Jenis Edge

Daftar jenis edge digunakan untuk menghemat ruang dengan mengizinkan jenis edge untuk kemudian direferensikan dengan pengenal bilangan bulat, bukan string yang seharusnya perlu diulang berkali-kali. Adapun jenis string edge yang telah ditentukan dapat dilihat pada tabel berikut:

Tabel III.2 Nilai String Jenis Edge

Nilai String Jenis Edge Keterangan

ENTRY Edge pertama dilalui dalam DCFG yang menjadi tanda dari mulainya node ke blok dasar pertama eksekusi

EXIT Edge terkahir dilalui dalam DCFG yang menjadi tanda dari berakhirnya node ke blok dasar akhir eksekusi

BRANCH Mewakilkan semua branch yang tidak diketahui CONDITIONAL_BRANCH Mewakilkan semua jenis conditional branch baik

direct maupun indirect

UNCONDITIONAL_BRANCH Mewakilkan semua jenis unconditional branch baik direct maupun indirect

DIRECT_BRANCH Sebuah direct untuk conditional branch INDIRECT_BRANCH Sebuah indirect untuk unconditional branch


(47)

DIRECT_CONDITIONAL_BRANCH Sebuah direct untuk conditional branch INDIRECT_CONDITIONAL_BRANCH Sebuah indirect untuk conditional branch DIRECT_UNCONDITIONAL_BRANCH Sebuah direct untuk unconditional branch INDIRECT_UNCODITIONAL_BRANCH Sebuah indirect untuk unconditional branch

REP Sebuah Edge yang mengindikasikan sebuah

instruksi dengan prefix “REP” atau repeated. FALL_THROUGH Sebuah Edge yang mengindikasikan instruksi pada

alamat selanjutnya telah dieksekusi.

CALL Mewakilkan semua jenis call yang tidak diketahui DIRECT_CALL Sebuah direct call yang mempunyai satu alamat

statis

INDIRECT_CALL Sebuah indirect call yang mempunyai satu alamat dinamis

RETURN Sebuah return biasanya dipanggil dari routine CALL_BYPASS Mengindikasikan control flow dalam sebuah routine

tanpa diikuti call

SYSTEM_CALL Sebuah call khusus ke sistem routine SYSTEM_RETURN Sebuah return dari sistem routine

SYSTEM_CALL_BYPASS Sama seperti CALL_BYPASS akan tetapi untuk sistem routine

CONTEXT_CHANGE Sebuah Edge yang dibuat dari semua instruksi non-control-flow

CONTEXT_CHANGE_RETURN Sebuah return dari handler context-change

CONTEXT_CHANGE_BYPASS Sama seperti CALL_BYPASS akan tetapi untuk handler context-change

EXCLUDED_CODE_BYPASS Sebuah Edge yang digunakan untuk memlihara control flow yang tidak termasuk wilayah kode dari CFG


(48)

5. Node Khusus

Daftar node khusus digunakan untuk menghemat ruang dengan mengizinkan node yang akan kemudian direferensikan oleh pengidentifikasi bilangan. Berikut yang harus diperhatikan adalah:

1. Parser tidak boleh berasumsi bahwa id dimulai dengan satu atau berurutan dalam urutan tertentu.

2. Parser tidak boleh berasumsi bahwa id tetap atau sama antara DCFG. Misalnya node “START” mungkin memiliki id=1 dalam satu DCFG dan id=3 di lain.

6. Data Proses

Semua data untuk proses disimpan dalam objek yang muncul di kolom PROCESS_DATA dari tabel PROSES. Kunci dalam objek dapat dilihat pada table sebagai berikut:

Tabel III.3 Proses Objek

Proses Objek Nilai

INSTR_COUNT Integer: jumlah instruksi untuk proses yang melewati seluruh thread

INSTR_COUNT_PER_THREAD Array: Setiap integer dari setiap jumlah insruksi untuk proses per-thread

IMAGES Tabel image

EDGES Tabel edge

7. Images

Semua images untuk suatu proses yang disimpan dalam tabel muncul setelah kunci IMAGES dalam proses data objek. Adapun klasifikasinya sebagai berikut: UNKNOWN Mewakilkan semua jenis Edge yang tidak diketahui


(49)

Tabel III.4 Images

Heading Nilai

IMAGE_ID Integer dapat dimulai dengan nol

LOAD_ADDR Sebuah integer yang mengandung alamat base yang dimuat oleh sistem operasi

SIZE Sebuah integer yang mengandung ukuran image IMAGE_DATA Sebuah objek JSON yang mengandung data image

8. Simbol

Semua simbol untuk images yang diberikan, disimpan dalam tabel yang muncul setelah kunci SYMBOLS dalam data objek images. Adapun klasifikasinya sebagai berikut:

Tabel III.5 Simbol Images

Heading Nilai

NAME String yang mengandung nama simbol

ADDR_OFFSET Integer yang mengandung alamat base dari relativitas simbol ke alamat load yang mengandung image

SIZE Sebuah integer yang mengandung ukuran simbol dalam bytes

9. Informasi Sumber

Semua informasi sumber debug images yang diberikan, disimpan dalam tabel yang muncul setelah kunci SOURCE_DATA dalam data objek images simbol. Adapun klasifikasinya sebagai berikut:


(50)

Tabel III.6 Informasi Sumber

Heading Nilai

FILE_NAME_ID Integer id dari nama file tabel yang mempresentasikan file sumber kode dari data debug

LINE_NUM Sebuah integer yang mempresentasikan garis nomor file referensi sumber kode

ADDR_OFFSET Sebuah integer yang mengandung alamat base dari relativitas data debug yang mengandung image

SIZE Sebuah integer yang mengandung ukuran data dalam bytes

NUM_INSTR Sebuah integer yang mengandung angka dari instruksi oleh data debug

10.Blok Dasar

Semua blok dasar untuk images yang diberikan, disimpan dalam tabel yang muncul setelah kunci BASIC_BLOCKS dalam images objek data informasi sumber. Sebuah blok dasar hanya memiliki satu poin entri dan satu titik keluar. Dasar blok didefinisikan secara dinamis, sehingga dapat bervariasi dari run-to-run pada beban kerja yang sama, hal ini bergantung pada edge dalam CFG yang dilalui. Variasi tersebut dapat mencakup tidak hanya blok dasar yang disertakan tetapi juga awal dan akhir alamat masing-masing. Adapun klasifikasinya dapat dilihat pada tabel berikut:


(51)

Tabel III.7 Blok Dasar

Heading Nilai

NODE_ID Sebuah integer id dan harus unik menyeluruh pada proses, tidak hanya image

ADDR_OFFSET Sebuah integer yang mengandung instruksi pertama dalam relativitas blok dasar ke alamat load dari image

SIZE Sebuah integer yang mengandung ukuran blok dala bytes NUM_INSTRS Sebuah integer yang mengandung angka instruksi dalam blok LAST_INSTR_OFFSET Sebuah integer yang mengandung alamat instruksi akhir dalam

relativitas blok dasar ke alamat pertama instruksi

COUNT Sebuah integer yang mengandung jumlah angka dari waktu blok yang telah dieksekusi menyeluruh pada thread

11.Routines

Semua informasi rutin untuk images yang diberikan, disimpan dalam tabel yang muncul setelah kunci ROUTINES dalam data objek images blok dasar. Rutinitas harus mengikuti aturan berikut:

1. Sebuah routine dapat memiliki hanya satu entri (routine dapat memiliki beberapa poin exit)

2. Setiap node dalam routines harus dicapai dari entri node. Hal ini berarti bahwa setiap node harus menjadi penerus langsung (target edge) dari entri node atau node lain dalam routines. Edge antar routine (call, returns, context changes, dll) tidak diperbolehkan dalam traversal tersebut. Namun, setiap node yang dicapai dari entri node tidak diperlukan untuk berada di routines yang sama. Hal tersebut memungkinkan untuk pembagian routines ketika ada beberapa node masuk, melompat antara routines dan kontrol aliran non-standar lainnya.


(52)

3. Setiap node dalam routines harus dalam images yang dikandung.

4. Setiap simpul dari suatu images (kecuali awal dan akhir) akan muncul di tepat satu routine.

Dengan demikian alamat dan ukuran routines tidak akan selalu sesuai dengan yang ada di tabel simbol. Routines juga dapat dimasukkan dengan edge selain calls dan dapat keluar selain returns. Adapun spesifikasinya dapat dilihat pada tabel berikut:

Tabel III.8 Routines

Heading Nilai

ENTRY_NODE_ID Sebuah integer id dari blok dasar

EXIT_NODE_IDS Array dari id blok dasar yang mengindikasikan satu atau lebih edges yang meninggalkan routine

NODES Tabel node

12.Loops

Semua informasi loop untuk routine disimpan dalam tabel yang muncul di bawah kolom LOOPS dalam tabel routine. Loop didefinisikan dengan algoritma standar graph-traversal. Kendala tersebut dapat diberlakukan sebagai berikut:

1. Sebuah loop hanya dapat memiliki satu head node 2. Sebuah loop dapat memiliki beberapa back-edge


(53)

Tabel III.9 Head Loop

Heading Nilai

LOOP_HEAD_NODE_ID Sebuah integer dari blok dasar pada head di loop

LOOP_BACK_EDGE_SOURCE_NODE_IDS Sebuah id integer blok dasar dari nodes yang mengandung branches kembali pada head di loop

LOOP_NODE_IDS Array dari id blok dasar untuk semua nodes dalam loop

PARENT_LOOP_HEAD_NODE_ID Sebuah id integer blok dasar dari head di node yang mengandung loop dalam routine

13.Edges

Semua informasi edge untuk proses tertentu disimpan dalam tabel yang muncul setelah tag EDGE dalam objek proses. Edge ditempatkan di luar data images karena edge sering keluar diantara images yang berbeda. Adapun spesifikasinya dapat dilihat pada tabel berikut:

Tabel III.10 Edges

Heading Nilai

EDGE_ID Sebuahid yang bernilai integer

SOURCE_NODE_ID Sebuah node id khusus atau id blok dasar dari control flow TARGET_NODE_ID Sebuah node ide khusus atau id blok dasar ke control flow EDGE_TYPE_ID Sebuah ide integer yang merupakan jenis edge

COUNT_PER_THREAD Array yang berisi integer dimana setiap integer berisi hitungan eksekusi untuk edge per-thread


(54)

III.1.6 Spesifikasi Intermediate Representation

Representasi menggunakan standar universal sebuah SSA (Static Single Assignment) dari LLVM karena ekspresif dalam human readable assembly language. Adapun spesifikasinya dapat diklasifikasikan sebagai berikut:

1. Identifiers

Identifier dibagi atas dua tipe dasar yaitu global dan local. Identifier global (functions, variabel global) dimulai dengan karakter „@‟. Identifier local (register names, types) dimulai dengan dengan karakter „%‟. Terdapat tiga format untuk identifier tergantung tujuan masing -masing:

1. Nilai yang mempunyai nama direpresentasikan sebagai string dengan prefix-nya. Contoh %foo dan @DivisionByZero. Identifier yang memerlukan karakter lain dalam penamaanya dikurung dengan tanda kutip dua. Karakter khusus di-escape menggunakan “\xx“ dimana xx adalah kode ASCII untuk karakter dalam hexademical. Prefix “\01“ dapat digunakan dalam variabel global untuk penekanan mangling.

2. Nilai yang tidak mempunyai nama direpresentasikan sebagai unsigned numeric dengan prefix-nya. Contoh %12 dan @2.

3. Konstan dibagi atas dua jenis yaitu simple dan dan complex. Konstan simple direpresentasikan dengan Boolean, Integer, Floating Point, Null Pointer dan Token sedangkan complex berupa Struktur, Array, Vector, Zero Initialization dan simpul metadata.

Prefix digunakan karena beberapa kata kunci seperti add, bitcast, ret untuk tipe data primitf seperti void dan i32 tidak boleh konflik dengan variabel nama.

Komentar dipisah dengan penandaan sebuah titik koma „;„ terus sampai akhir

baris.

2. Linkage Types

Semua variabel global dan fungsi mempunyai setidaknya satu dari tipe linkage. Hal ini dapat dilihat seperti pada tabel berikut:


(55)

Tabel III.11 Linkage Types

No Linkage Type Keterangan

1 private Nilai global dengan linkage“private“ hanya dapat diakses langsung oleh objek – objek dalam modulnya

2 internal Sama dengan “private“ akan tetapi nilai dimunculkan sebagai simbol lokal (STB_LOCAL pada ELF) dalam file objek

3 available_externally Global dengan tanda “available_externally” mengizinkan inlining dan optimasi lainny sebagai pengetahuan definisi global diluar modul tersebut.

4 linkonce Global dengan linkage “linkonce“ menandakan penggabungan dengan global lainnya yang mempunyai nama sama ketika linkage terjadi

5 weak Secara semantik sama dengan linkage linkonce kecuali referensinya bisa jadi tidak dihapus

6 common Sebagian besar mirip dengan “weak” tetapi linkage “common” digunakan untuk definisi sementara pada C seperti “int X;” pada skala global

7 appending Global “appending” hanya diterapkan pada variabel pointer ke tipe array

8 extern_weak Semantik linkage ini mengikuti model file objek pada ELF yang mana akan selalu null jika tidak linked

9 linkonce_odr Linkage ini untuk mengindikasikan bahwa global akan selalu digabungkan bersama global yang setara lainnya

10 external Linkage “external“ digunakan jika tidak ada satupun identifier yang dipakai, artinya dapat digunakan dalam menyelesaikan simbol eksternal


(56)

3. Visibility Styles

Seluruh variabel global dan fungsi pada ELF setidaknya mempunyai visibility styles. Hal tersebut dapat dilihat dalam tabel berikut:

Tabel III.12 Visibility Styles No Visibility

Style

Keterangan

1 default Deklarasi tampak untuk modul lainnya dalam shared libraries 2 hidden Mengindikasikan bahwa simbol tidak akan ditempatkan dalam tabel

simbol dinamis

3 protected Menyatakan bahwa simbol akan ditempatkan dalam tabel simbol dinamis tetapi tidak dapat di-override oleh modul lain

Sebuah simbol dengan linkage internal atau private harus mempunyai

“default” visibility. Hal ini dikarenakan setiap pustaka saling berkaitan satu sama lain

4. Comdats

Comdat adalah sebuah objek yang mengandung paket fungsi dan data. Pada Intermediate Representation berisi akses untuk COFF dan file objek ELF. Comdat memiliki seleksi jenis untuk menyediakan input dalam bagaimana linker harus memilih antara kunci dalam dua file objek berbeda.

Syntax:

$<Name> = comdat JenisSeleksi


(57)

Tabel III.13 COMDAT

No Jenis Seleksi Keterangan

1 any Linker memilih kunci COMDAT yang mana saja secara acak. 2 exactmatch Linker memilihkunci COMDAT yang mana saja tetapi seksi harus

mengandung data yang sama

3 largest Linker memilih seksi yang mengandung kunci COMDAT paling besar

4 noduplicates Linker memilih kunci COMDAT yang paling unik pada seksi 5 samesize Linker memilih kunci COMDAT yang mana saja tetapi seksi harus

mengandung banyaknya data yang sama

5. Atribut Parameter

Setiap parameter sebuah tipe fungsi memiliki sebuah atribut parameter yang terkait satu sama lain. Atribut parameter digunakan untuk komunikasi informasi tambahan tentang hasil atau parameter sebuah fungsi. Atribut parameter dianggap sebagai bagian dari fungsi, bukan tipe fungsi, dengan kata lain fungsi – fungsi dengan atribut parameter berbeda dapat memiliki tipe fungsi yang sama. Atribut parameter didefinisikan sebagai berikut:

Tabel III.14 Atribut Parameter

No Parameter Keterangan

1 zeroext Mengindikasikan ke kode generator bahwa parameter atau nilai kembali harus zero-extended untuk jangkauannya dimana diperlukan oleh caller untuk parameter dan callee untuk nilai kembali

2 signext Mengindikasikan ke kode generator bahwa parameter atau nilai kembali harus sign-extended untuk jangkauannya dimana diperlukan oleh caller untuk parameter dan callee untuk nilai kembali


(58)

3 inreg Mengindikasikan bahwa parameter atau nilai kembali harus dianggap spesifik dalam targetnya dengan menempatkannya dalam register sebagai penentang ke memori

4 byval Mengindikasikan bahwa penunjuk parameter harus melewati nilai untuk menuju ke fungsi

5 inalloca Atribut inalloca membolehkan caller untuk mengambil alamat pernyataan stack yang sedang berjalan

6 sret Mengindikasikan parameter pointer menspesifikasikan alamat sebuah struktur yang mana nilai kembali merupakan fungsi dalam sumber program

7 align Mengindikasikan bahwa nilai pointer diasumsikan oleh optimizer untuk mempunyai spesifikasi alignment

8 noalias Mengindikasikan bahwa objek diakses dengan nilai – nilai pointer berdasarkan pernyataan atau nilai kembali

9 nocapture Mengindikasikan bahwa callee tidak membuat salinan pointer yang dipakai lebih lama dari callee itu sendiri

10 nest Mengindikasikan bahwa parameter pointer dapat dipotong menggunakan trampoline instrincs

11 returned Mengindikasikan bahwa fungsi selalu mengembalikan pernyataan sebagai nilai kembali

12 nonnull Mengindikasikan bahwa parameter atau pointer kembali tidak null

13 dereferenceable Mengindikasikan bahwa parameter atau pointer kembali dereferenceable

14 Dereferenceable_or_null Mengindikasikan bahwa parameter atau nilai kembali bukan non-null atau non-dereferenceable pada saat yang sama

6. Atribut Fungsi

Atribut fungsi adalah set komunikasi informasi tambahan tentang sebuah fungsi yang berupa kata kunci sederhana mengikuti spesifikasi tipe. Atribut dapat


(1)

TEST(DYNSMC, getcwd) { char path[PATH_MAX + 1];

char* res = getcwd(path, sizeof(path)); ASSERT_TRUE(res != NULL);

EXPECT_NOT_POISONED(path[0]); }

7.

Shared Memory

Pengujian

shared memory

dari pemanggilan proses

TEST(DYNSMC, shmat) {

void *p = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_NE(MAP_FAILED, p);

((char *)p)[10] = *GetPoisoned<U1>(); ((char *)p)[4095] = *GetPoisoned<U1>(); int res = munmap(p, 4096);

ASSERT_EQ(0, res);

int id = shmget(IPC_PRIVATE, 4096, 0644 | IPC_CREAT);

ASSERT_GT(id, -1);

void *q = shmat(id, p, 0); ASSERT_EQ(p, q);

EXPECT_NOT_POISONED(((char *)q)[0]); EXPECT_NOT_POISONED(((char *)q)[10]); EXPECT_NOT_POISONED(((char *)q)[4095]); res = shmdt(q);

ASSERT_EQ(0, res);

res = shmctl(id, IPC_RMID, 0); ASSERT_GT(res, -1);


(2)

8.

Pembacaan Direktori

Pengujian baca direktori dilakukan untuk memeriksa apakah

program dapat membaca direktori atau tidak

TEST(DYNSMC, readdir) { DIR *dir = opendir(".");

struct dirent *d = readdir(dir); ASSERT_TRUE(d != NULL);

EXPECT_NOT_POISONED(d->d_name[0]); closedir(dir);

}

9.

Canonicalized Path

Pengujian absolut

pathname

merupakan pengecekan apakah target

program adalah

symbolic links

atau tidak

TEST(DYNSMC, realpath) { const char* relpath = "."; char path[PATH_MAX + 1];

char* res = realpath(relpath, path); ASSERT_TRUE(res != NULL);

EXPECT_NOT_POISONED(path[0]); }

10.

Environment Variable

Pengujian untuk mengganti dan mengubah nilai

environ

pada

shell

TEST(DYNSMC, putenv) {

char s[] = "AAA=BBB"; putenv(s);

for (char **envp = environ; *envp; ++envp) {

EXPECT_NOT_POISONED(*envp); EXPECT_NOT_POISONED(*envp[0]); }


(3)

11.

Penyalinan Memori

Pengujian fungsi salin memori pada dari

source

ke

destination

TEST(DYNSMC, memcpy) {

char* x = new char[2]; char* y = new char[2]; x[0] = 1;

x[1] = *GetPoisoned<char>(); memcpy(y, x, 2);

EXPECT_NOT_POISONED(y[0]); EXPECT_POISONED(y[1]); }

12.

Penyalinan String

Pengujian fungsi salin

string

dari

source

ke

destination

TEST(DYNSMC, strcpy) {

char* x = new char[3]; char* y = new char[3]; x[0] = 'a';

x[1] = *GetPoisoned<char>(1, 1); x[2] = 0;

strcpy(y, x); // NOLINT EXPECT_NOT_POISONED(y[0]); EXPECT_POISONED(y[1]); EXPECT_NOT_POISONED(y[2]); }

13.

Cetak Keluaran


(4)

TEST(MemorySanitizer, dr_printf) { char buff[10];

break_optimization(buff); EXPECT_POISONED(buff[0]);

int res = dr_printf(buff, "%d", 1234567); ASSERT_EQ(res, 7);

ASSERT_EQ(buff[0], '1'); ASSERT_EQ(buff[1], '2'); ASSERT_EQ(buff[2], '3'); ASSERT_EQ(buff[6], '7'); ASSERT_EQ(buff[7], 0); EXPECT_POISONED(buff[8]); }

14.

Timestamp

Pengujian

timestamp

dilakukan untuk memperoleh

interval

waktu

eksekusi

TEST(DYNSMC, time) { time_t t;

EXPECT_POISONED(t); time_t t2 = time(&t); ASSERT_NE(t2, (time_t)-1); EXPECT_NOT_POISONED(t); }

15.

Penggunan Resource

Pengujian penggunaan kesuluruhan

resource

program

TEST(DYNSMC, getrusage) { struct rusage usage;

__dyn_poison(&usage, sizeof(usage));

int result = getrusage(RUSAGE_SELF, &usage);

ASSERT_EQ(result, 0);


(5)

EXPECT_NOT_POISONED(usage.ru_utime.tv_usec); EXPECT_NOT_POISONED(usage.ru_stime.tv_sec);

EXPECT_NOT_POISONED(usage.ru_stime.tv_usec); EXPECT_NOT_POISONED(usage.ru_maxrss); EXPECT_NOT_POISONED(usage.ru_minflt); EXPECT_NOT_POISONED(usage.ru_majflt); EXPECT_NOT_POISONED(usage.ru_inblock); EXPECT_NOT_POISONED(usage.ru_oublock); EXPECT_NOT_POISONED(usage.ru_nvcsw); EXPECT_NOT_POISONED(usage.ru_nivcsw); }

16.

Operasi Bit

Pengecekan

circular shift

TEST(DYNSMC, LLVMOp) {

if (!TrackingOrigins()) return; BinaryOpOriginTest<S8>(XOR<S8>); BinaryOpOriginTest<U8>(ADD<U8>); BinaryOpOriginTest<S4>(SUB<S4>); BinaryOpOriginTest<S4>(MUL<S4>); BinaryOpOriginTest<U4>(OR<U4>); BinaryOpOriginTest<U4>(AND<U4>); BinaryOpOriginTest<double>(ADD<U4>); BinaryOpOriginTest<float>(ADD<S4>); BinaryOpOriginTest<double>(ADD<double>); BinaryOpOriginTest<float>(ADD<double>); }

IV.2.1.3 Hasil Unit Testing

Berdasarkan pembangunan

unit testing

selanjutnya diserahkan pada

runner

atau kompilasi terhadap program

testing.

Dari pengamatan diatas diperoleh

keluaran sebagai berikut:


(6)

Running main() from gtest_main.cc

[==========] Running 16 tests from 1 test cases. [———-] Global test environment set-up.

[———-] 16 tests from DYNSMC

[ RUN ] DYNSMC.gagalBukaFile

[ OK ] DYNSMC.gagalBukaFile (0 ms) [ RUN ] DYNSMC.Malloc

[ OK ] DYNSMC.Malloc (0 ms) [ RUN ] DYNSMC.StackTest

[ OK ] DYNSMC.StackTest (0 ms) [ RUN ] DYNSMC.StackTest

[ OK ] DYNSMC.StackTest (0 ms)

---dipotong---

[———-] 16 tests from DYNSMC (0 ms total) [———-] Global test environment tear-down

[==========] 16 tests from 1 test cases ran. (0 ms total) [ PASSED ] 16 tests.

IV.2.2 Wawancara

Wawancara menggunakan media

e-mail

dengan para pengembang

DynamoRIO framework

dimana program diajukan untuk daftar

plugin

eksternal.

Dari hasil diskusi dapat disimpulkan bahwa modul yang dibangun sangat mudah

digunakan karena dilengkapi

build

script, kebutuhan analisis

Self-Modifying Code

tersedia serta tidak ada kendala dari segi

deprecated

API ataupun mendapatkan

pustaka

dependencies.