Menyematkan kode dan bahaya perangkat lunak bajakan

Tentang bagaimana Anda dapat menyematkan kode tanpa jmp di bagian kode dan tetap tidak terlihat jika Anda tidak mempelajari kode yang dibongkar secara menyeluruh. Siapa yang peduli, tolong, di bawah kucing.

Saya mengembangkan disassembler C untuk Linux. Tentang diri saya, saya tidak akan mengatakan bahwa saya seorang programmer profesional. Saya tidak bekerja sebagai programmer, tetapi yang saya pelajari adalah membaca buku, atau menciptakannya sendiri, atau mempelajari kode sumber program lain. Karena itu, jika kode itu kekanak-kanakan bagi Anda, jangan bersumpah.

Sebagai permulaan, saya melakukan disassembler dan kode saya sekarang terlihat seperti ini, yaitu, byte dibaca dan diteruskan ke fungsi yang diinginkan.

void disasm_intel ( unsigned char *ptr, int size, int byte_order, int show ) { show_asm = show; virt = global_virt_text; unsigned char *start = ptr; start_op = ptr; for ( int index = 0; index < size; index++ ) { if ( show_asm == TRUE ) printf ( "%lx: ", virt ); switch ( *ptr ) { case 0x30: intel_opcode_1_0x30 ( &ptr, &index, byte_order ); break; case 0x31: intel_opcode_1_0x31 ( &ptr, &index, byte_order ); break; case 0x66: intel_opcode_1_0x66 ( &ptr, &index, byte_order ); break; case 0x67: intel_opcode_1_0x67 ( &ptr, &index, byte_order ); break; case 0x83: intel_opcode_1_0x83 ( &ptr, &index, byte_order ); break; case 0x88: intel_opcode_1_0x88 ( &ptr, &index, byte_order ); break; // mov register to register byte case 0x89: intel_opcode_1_0x89 ( &ptr, &index, byte_order ); break; case 0x8a: intel_opcode_1_0x8a ( &ptr, &index, byte_order ); break; case 0x8b: intel_opcode_1_0x8b ( &ptr, &index, byte_order ); break; // mov esp, %x : mov ebp, %x case 0x8d: intel_opcode_1_0x8d ( &ptr, &index, byte_order ); break; // lea case 0xb0: intel_opcode_1_0xb0 ( &ptr, &index ); break; // mov al, %x case 0xb1: intel_opcode_1_0xb1 ( &ptr, &index ); break; // mov cl, %x case 0xb2: intel_opcode_1_0xb2 ( &ptr, &index ); break; // mov dl, %x case 0xb3: intel_opcode_1_0xb3 ( &ptr, &index ); break; // mov bl, %x case 0xb4: intel_opcode_1_0xb4 ( &ptr, &index ); break; // mov ah, %x case 0xb5: intel_opcode_1_0xb5 ( &ptr, &index ); break; // mov ch, %x case 0xb6: intel_opcode_1_0xb6 ( &ptr, &index ); break; // mov dh, %x case 0xb7: intel_opcode_1_0xb7 ( &ptr, &index ); break; // mov bh, %x case 0xb8: intel_opcode_1_0xb8 ( &ptr, &index, byte_order ); break; // mov eax, %x case 0xb9: intel_opcode_1_0xb9 ( &ptr, &index, byte_order ); break; // mov ecx, %x case 0xba: intel_opcode_1_0xba ( &ptr, &index, byte_order ); break; // mov edx, %x case 0xbb: intel_opcode_1_0xbb ( &ptr, &index, byte_order ); break; // mov ebx, %x case 0xbe: intel_opcode_1_0xbe ( &ptr, &index, byte_order ); break; // mov esi, %x case 0xbf: intel_opcode_1_0xbf ( &ptr, &index, byte_order ); break; // mov edi, %x case 0xc3: intel_opcode_1_0xc3 ( ); break; // ret case 0xcd: intel_opcode_1_0xcd ( &ptr, &index ); break; // int 0x%x } ptr++; virt += ptr - start; start = ptr; start_op = ptr; } show_asm = FALSE; } 

Dan fungsi seperti itu sudah banyak. Di beberapa tempat saya membuat komentar untuk menangkap interkoneksi instruksi mesin, dan mungkin kemudian membuat disassembler yang lebih kompeten. Tetapi dalam bentuk ini, di mana saya memiliki kode sekarang, saya dapat dengan mudah mengatur kondisi untuk setiap operator.

Jadi ketika saya melakukan ini, saya punya ide, apakah mungkin untuk menambahkan kode di tengah bagian kode? Ternyata Anda bisa, tetapi dalam semua kasus? Sejauh ini, untuk menambahkan kode, saya menggunakan kode mesin yang sudah disiapkan. Jika saya bisa nanti, maka saya akan membuat assembler translator dalam kode mesin untuk menambahkan kode lebih nyaman. Dalam kasus saya, Anda perlu menentukan offset di bagian kode dan byte disalin ke tempat yang tepat. Ada juga masalah tertentu: pengalamatan dalam memori. Saya menambahkan kode ke perintah lea yang menyimpan data yang diperlukan dalam struktur, dan jika Anda memasukkan operator baru ke dalam bagian kode, maka semua offset disejajarkan sehingga mereka menunjukkan data pada offset baru. Yah, itu tidak terlalu sulit, jika Anda memasukkan kode, bagian kode bertambah dengan jumlah byte yang sama dan semua bagian lainnya setelah bagian kode sudah mengandung offset baru. Saya membuatnya sehingga ada perbedaan di mana Anda menempelkan kode, semua offset bekerja dengan benar. Maka timbul masalah bahwa dalam menyikapi hal tersebut

 mov eax, [eax + eax + 0x100] 

Faktanya adalah bahwa dalam pengalamatan seperti itu bisa ada ebp dan arahkan ke stack, dan bukan ke bagian lain. Saya memutuskan untuk membuatnya sehingga jika alamat menunjuk ke bagian data, maka pertimbangkan offset saat memasukkan kode, jika menunjuk ke tumpukan, yaitu, bukan alamat di bagian data, maka jangan memperhitungkan offset.

Dan dengan cara ini penyerang bisa memanfaatkan. Lagi pula, kode jahat dapat dimasukkan di awal beberapa fungsi dalam program, misalnya, sehingga anak garpu dibuat dan file khusus diunduh. Di Linux, ini bisa dilakukan tanpa masalah. Memang, di / usr / sertakan ada file dengan semua fungsi sistem dari sistem operasi. Artinya, Anda dapat menggunakan bagian jaringan, bahkan jika program tidak memiliki fungsi jaringan. Saya tidak tahu caranya di windows, tetapi saya akan mencoba menambahkan pekerjaan dengan format pe nanti. Itu bisa berubah untuk melakukan hal yang sama seperti di Linux. Sejauh ini saya memiliki versi konsol. Tapi kemudian saya berencana untuk melakukannya di GTK.

Terima kasih telah menghabiskan waktu Anda di artikel saya.

Source: https://habr.com/ru/post/id477590/


All Articles