-
Notifications
You must be signed in to change notification settings - Fork 58
/
samsung_cid.c
155 lines (115 loc) · 3.05 KB
/
samsung_cid.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include "mmc.h"
#include <sys/reboot.h>
#define CID_SIZE 16
#define PROGRAM_CID_OPCODE 26
#define SAMSUNG_VENDOR_OPCODE 62
#define CID1 "/sys/devices/msm_sdcc.1/mmc_host/mmc0/mmc0:0001/cid"
#define CID2 "/sys/devices/platform/msm_sdcc.1/mmc_host/mmc0/mmc0:0001/cid"
#define CID3 "/sys/class/mmc_host/mmc0/mmc0:0001/cid"
int mmc_movi_vendor_cmd(unsigned int arg, int fd) {
int ret = 0;
struct mmc_ioc_cmd idata = {0};
idata.data_timeout_ns = 0x10000000;
idata.write_flag = 1;
idata.opcode = SAMSUNG_VENDOR_OPCODE;
idata.arg = arg;
idata.flags = MMC_RSP_R1B | MMC_CMD_AC;
ret = ioctl(fd, MMC_IOC_CMD, &idata);
return ret;
}
int cid_backdoor(int fd) {
int ret;
mmc_movi_vendor_cmd(0xEFAC62EC, fd);//enter vendor
mmc_movi_vendor_cmd(0xEF50, fd);//cid backdoor set
ret = mmc_movi_vendor_cmd(0x00DECCEE, fd);//exit vendor
return ret;
}
int get_cid(char *cid) {
/* this is hacky way to read CID from sysfs, ioctl doesn't seem to want to cooperate
if your cid isn't in one of the predefined paths, update the code*/
int fd, i;
char buf[32] = {0};
fd = open(CID1, O_RDONLY);
if(fd < 0){
fd = open(CID2, O_RDONLY);
if(fd < 0) {
fd = open(CID3, O_RDONLY);
if(fd < 1) return -1;
}
}
if(read(fd, buf, CID_SIZE*2) != CID_SIZE*2) return -1;
for(i = 0; i < CID_SIZE; i++){
sscanf(&buf[i*2], "%2hhx", &cid[i]);
}
return 0;
}
int program_cid(int fd, char *cid) {
int ret;
struct mmc_ioc_cmd idata = {0};
idata.data_timeout_ns = 0x10000000;
idata.write_flag = 1;
idata.opcode = PROGRAM_CID_OPCODE;
idata.arg = 0;
idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
idata.blksz = CID_SIZE;
idata.blocks = 1;
idata.data_ptr = (__u64)(unsigned int)cid;
ret = ioctl(fd, MMC_IOC_CMD, &idata);
return ret;
}
int is_samsung_emmc(char *cid) {
return (cid[0] == 0x15) ? 1 : 0;
}
void show_cid(char *cid) {
int i;
printf("[+] CID at boot time is/was: ");
for(i = 0; i < CID_SIZE; i++){
printf("%02x", cid[i]);
}
printf("\n");
}
void main(int argc, const char **argv) {
int fd, ret, i;
char cid[CID_SIZE] = {0};
char old_cid[CID_SIZE] = {0};
if(get_cid(old_cid) < 0) {
printf("[-] can't get current CID, find it and fix the code\n");
return;
}
show_cid(old_cid);
if(!is_samsung_emmc(old_cid)) {
printf("[-] don't try this on non-samsung eMMC, seriously.\n");
return;
}
if(argc != 2 || strlen(argv[1]) != CID_SIZE*2) {
printf("[-] RTFC!! ./samsung_cid [NEW_CID]\n");
return;
}
for(i = 0; i < CID_SIZE; i++){
ret = sscanf(&argv[1][i*2], "%2hhx", &cid[i]);
if(!ret){
printf("[-] CID should be HEX!\n");
return;
}
}
printf("[+] programming new CID %s\n", argv[1]);
fd = open("/dev/block/mmcblk0", O_RDWR);
if(fd < 0){
printf("[-] wtf\n");
return;
}
ret = cid_backdoor(fd);
if(ret){
printf("[-] cid_backdoor failed %d\n", ret);
return;
}
ret = program_cid(fd, cid);
if(ret){
printf("[-] program_cid failed %d\n", ret);
}
printf("[+] success! powering off device, power back on and verify CID\n");
reboot(LINUX_REBOOT_CMD_POWER_OFF);
}