Menulis driver laptop untuk bersenang-senang dan untung, atau Cara berkomitmen untuk kernel bahkan jika Anda tidak sepintar itu

Di mana semuanya dimulai


Mari kita mulai dengan pernyataan masalah kita. Kami memiliki 1 (satu) laptop. Laptop gamer baru. Dengan beberapa RGB-backlight pada keyboard-nya. Ini terlihat seperti ini:

gambar
Gambar diambil dari lenovo.com

Ada juga program yang diinstal di laptop ini. Itulah hal yang mengontrol cahaya latar kami.

Satu masalah - program berjalan di bawah Windows, dan kami ingin semuanya berjalan di Linux favorit kami. Ingin LED berkedip dan warna-warna cantik itu berkedip dan mati dan semacamnya. Sebuah pertanyaan alami muncul, dapatkah kita melakukan semua itu tanpa rekayasa balik dan menulis driver kita sendiri?

Jawaban alami muncul, tidak. Mari buka IDA dan dapatkan cracking.



Langkah 1 - Menggali kode


Ada tiga pemicu yang membuat lampu latar menyala. Dalam urutan kesulitan naik:

1. Program penggemar gim besar bernama Lenovo Nerve Center, yang memiliki menu penyiapan penggemar besar hanya untuk lampu latar ini.

2. Kombinasi tombol pintas Fn + Spasi - mungkin dikelola oleh program tersebut juga.

3. BIOS. Saat laptop sedang memuat, lampu latar berkedip merah untuk sesaat. Mungkin kita bisa menggunakannya?

Saya harus mencoba semua 3. Tapi ada beberapa keberhasilan hanya di sepanjang yang pertama, jadi mari kita bicara tentang yang pertama di sini.

Kami membuka folder dengan program kami:

folder

Perhatikan di sini! Ada DLL dengan nama yang sangat menarik - LedSettingsPlugin.dll. Mungkinkah ...? Mari kita buka di IDA Pro dan lihat sendiri.

setengah benar

Lihatlah bagian kanan layar di sini - begitu, begitu banyak informasi debug! Mari kita gunakan. Beberapa string terlihat seperti nama fungsi di sini. Saya bertanya-tanya mengapa ...

nama-fungsi

Oh, ini adalah nama-nama fungsi. Nyaman! Mari kita memanggil beberapa hal dengan nama mereka sendiri dan kemudian melihat daftar fungsi lagi. Untuk memberi nama hal-hal di IDA Anda dapat menggunakan hotkey N, atau klik kanan hal yang ingin Anda beri nama.

setledstatusex

Melihat fungsi, kita melihat sesuatu yang disebut Y720LedSetHelper :: SetLEDStatusEx. Sepertinya yang kita butuhkan! Ini membentuk semacam string, dan kemudian memberikannya ke sesuatu yang disebut CHidDevHelper :: HidRequestsByPath. Bagian yang menarik yang harus kita lihat adalah var_38, disorot dengan penuh kasih sayang oleh IDA.

Var_34 juga menarik. Ini berjalan tepat setelah var_38 - dalam tradisi assembler, variabel disimpan dalam urutan terbalik di bawah RSP. Var_34 di IDA hanyalah nama dari konstanta - -34h.

Mulai dari var_38, program kami menempatkan nol, kemudian gaya, warna, nomor tiga dan blok - bagian keyboard yang akan mendapatkan warna ini. (Kemudian, percobaan akan menunjukkan bahwa nomor tiga sebenarnya kecerahan. Menambahkan kontrol yang akan membuat pengemudi kami lebih baik daripada yang resmi!)

Sekarang, mari kita menyelam ke dalam HidRequestsByPath dan mencoba mencari tahu apa yang perlu kita kirim dan ke mana.

penyembah

Lihat, dua fungsi. HidD_GetFeature dan HidD_SetFeature.

Mereka tidak dilacak dalam file ... tetapi dilacak dengan sangat baik dalam dokumentasi resmi Microsoft - di sini dan di sini .

Kita bisa menepuk punggung kita sendiri sekarang. Ini adalah dasar batu, tidak ada tempat untuk menggali lebih dalam. Linux memiliki dua fungsi tersebut - kami baru saja kembali, dan memanggil mereka dengan argumen yang sama. ... benar?

Langkah 2 - meluncurkan prototipe ...?



Tidak juga. Ayo kembali ke Linux dan buka lsusb. Kami akan menemukan keyboard kami di sana, dan kami akan mengirim sesuatu ke sana.

lsusb

Integrated Technology Express, Inc. adalah yang paling menarik di sini. Mari kita gunakan alat / dev / hidraw yang populer. Kita dapat menemukan yang tepat hanya dengan melihat / sys / class / hidraw / hidraw * / device / uevent yang sesuai.

hidraw

Yang ini Semua digit cocok - itu artinya / dev / hidraw0 adalah perangkat kami. Tapi mari kita coba mengirim sesuatu ... dan tidak ada yang terjadi! Mengapa Pada titik ini, burnout terjadi. Mungkin ini bukan hanya untuk manusia biasa, teknik reverse engineering ini?

Tapi mari kita terus berusaha. Jika pengarangnya lebih ahli dalam hal ini, dia akan membalikkan Nerve Center lagi dan menghasilkan solusi ... Tapi kita tidak punya otak. Mari kita reboot ke Windows, ada ide.

Ada hal ini di Windows - Device Manager, mereka menyebutnya. Memiliki banyak fungsi - tetapi kami tertarik pada satu. Ini memungkinkan Anda untuk menonaktifkan perangkat. Sederhana dan berwibawa.

Jadi mari kita nonaktifkan semua perangkat sampai LED kita berhenti berkedip!

nonaktifkan perangkat

Ini berhasil. Jika kita mengintip ID Hardware-nya - kita akan lihat apa itu, perangkat LED yang misterius itu.

perangkat kami

Lihat - ini dia.

dmesg

Perangkat yang telah mengganggu dmesg saya selama beberapa tahun.

[Kenapa itu tidak ditampilkan di lsusb? Ini bukan USB sama sekali, tentu saja! Lampu latar menggunakan protokol yang disebut I2C HID - memungkinkan produsen untuk menyembunyikan perangkat dari tangan orang jahat DIY memasang gadget HID ke bus sistem komputer itu sendiri.]

Sidestep 2.5 - mari kita membuat komit


Pencarian untuk perangkat yang benar ini telah banyak diringkas. Dalam penceritaan asli, saya harus membuka pengaturan saya hampir sampai ke kernel sebelum saya menyadari mengapa tidak ada yang berhasil. Juga, saya tidak menikmati log dmesg ini yang muncul sendiri setiap kali saya membuka kunci komputer saya. Karena kita di sini - mengapa tidak pergi dan menulis komit singkat?

Kita perlu menemukan dua hal - tempat di mana perangkat H2C I2C ditangani, dan tempat di mana kebiasaan mereka disimpan. Di sini Jangan berpikir terlalu keras dan lihat kesalahannya: laporan tidak lengkap. Mari kita selesaikan.

ukuran input buruk

Tambahkan kekhasan baru, sebut saja I2C_HID_QUIRK_BAD_INPUT_SIZE atau sesuatu seperti itu. Untuk menjaga tema.

kekhasan

Juga mari kita tambahkan perangkat kita ke daftar quirked. Apa yang telah kami lakukan sejauh ini:

1. Mencari β€œi2c hid linux kernel” di mesin pencari. Mengklik hasil ke-4 di DuckDuckGo.

2. Tulis tiga (!) Kata dalam Bahasa Inggris - BAD_INPUT_SIZE

3. Menambahkan satu ke BIT (4). Hasil - BIT (5).

4. Menambahkan nomor ke hid-id.h - ID perangkat kami (tidak diilustrasikan, tetapi kesulitannya serupa)

Kami programmer, mari kita lakukan pemrograman sekarang.

Lihat garis:
ret_size = ihid->inbuf[0] | ihid->inbuf[1] << 8;

Dan kemudian mengeluh bahwa ret_size bukan yang itu.

Setiap kali kekhasan kita aktif, mari kita lakukan ini tetapi mundur.

jika-kondisi

Kirim tambalan ke milis ... (ujilah sebelumnya!). Sejujurnya, masuk ke milis itu lebih sulit daripada tambalan yang sebenarnya. Itu tidak sederhana dengan cara apa pun.

diterapkan

Itu dia!

Langkah 3 - driver!


Pada titik ini saya ingat - saya mencoba untuk menulis driver. Memutuskan saya belum akan melakukan itu ke kernel - pertanyaan mulai muncul, pada titik ini Anda benar-benar harus memikirkan beberapa. Jika ada yang membaca ini pandai kernel dan dapat berkonsultasi dengan saya, saya akan senang untuk berbicara.

Mari kita buka python. (Dulu bash, tetapi Anda berubah pikiran dengan sangat cepat dengan bahasa semacam itu). Mari kita gunakan alat / dev / hidraw yang populer.

/ dev / hidraw0, / dev / hidraw1 - bagaimana cara kerja file-file itu? Untuk I / O sederhana, Anda dapat menggunakannya seperti yang lain, dan sepertinya itu hanya akan berfungsi. Dan GetFeature dan SetFeature - yah, itu cerita yang sama sekali berbeda.

StackOverflow (atau orang lain, saya tidak ingat) mengatakan kepada saya bahwa saya harus melihat sesuatu yang disebut ioctl. Ini adalah cara khusus untuk bekerja dengan file yang tidak biasa seperti perangkat HID, terminal dan hal-hal menjijikkan serupa.

Tampaknya sederhana di permukaan - Anda memberinya pegangan file terbuka (bukan tingkat Python, tingkat OS! Baca lebih lanjut tentang pegangan OS di sini jika Anda ingin tahu.), Beberapa nomor dan buffer - dan kemudian melakukannya sesuatu dengan buffer itu dan mengembalikannya kepada Anda. Saya tidak mencoba untuk menjadi cerdas di sini, hanya saja itu hampir sepenuhnya tergantung pada implementasi. Berikut ini contohnya: 0xC0114806. Apa itu Itu SetFeature. Itu juga

(6 << 29) | (ord('H') << 8) | (0x06 << 0) | (0x11 << 16).

6 pertama berarti file akan terbuka baik untuk membaca maupun untuk menulis. Kami hanya menulis, tetapi dokumen mengatakan 6 yang berarti kami menempatkan 6. Ord ('H') adalah singkatan dari HID. Terkadang singkatan dari hal-hal lain, tergantung pada file. Tapi sekarang HID.

0x06 adalah perintah itu sendiri. Perintah keenam dari HID adalah SetFeature, yang kita butuhkan. Dan bagian terakhir? Ukuran buffer.

Yang tersisa hanyalah menyatukannya menjadi panggilan ioctl, dan Anda mendapatkan driver. Itu bekerja. .

Kata penutup dari penulis


Semoga artikel itu menarik dibaca. Bahkan bacaan yang bermanfaat, mungkin. Beberapa bagian dihilangkan atau disingkat menjadi singkat - pembaca yang lebih jeli mungkin memperhatikan bahwa pengemudi dapat membaca keadaan keyboard saat ini, dan fungsi set_status memiliki panggilan ioctl kedua yang bahkan tidak disebutkan dalam teks. Pengembangan perangkat keras dan kernel Linux adalah hal-hal besar, dan satu kisah tidak akan mencakup semuanya. Dan pada akhirnya, mungkin artikelnya bukan tentang ini. Mungkin itu hanya tentang bagaimana melakukan sesuatu yang kecil dan baik, untuk open-source atau untuk diri sendiri, tidak sulit sama sekali. Anda hanya perlu menemukan malam gratis senilai satu minggu, teh dan keinginan untuk menggali kode.

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


All Articles