• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "object.h"
17 
18 #include "utils/logger.h"
19 
20 #include "configs/guard_context.h"
21 #include "program.h"
22 #include "util/assert_util.h"
23 #include "util/string_util.h"
24 
25 namespace {
26 constexpr std::string_view TAG = "[Object]";
27 constexpr size_t LITERAL_OBJECT_ITEM_LEN = 2;
28 constexpr size_t LITERAL_OBJECT_COMMON_ITEM_GROUP_LEN = 4;  // Every 4 elements represent a set of regular key values
29 constexpr size_t LITERAL_OBJECT_METHOD_ITEM_GROUP_LEN = 6;  // Every 6 elements represent a set of regular key values
30 }  // namespace
31 
ExtractNames(std::set<std::string> & strings) const32 void panda::guard::ObjectProperty::ExtractNames(std::set<std::string> &strings) const
33 {
34     strings.emplace(this->name_);
35 }
36 
Build()37 void panda::guard::ObjectProperty::Build()
38 {
39     if (this->method_ == nullptr) {
40         return;
41     }
42 
43     this->method_->nameNeedUpdate_ = this->needUpdate_;
44     this->method_->Init();
45     this->method_->Create();
46 }
47 
Update()48 void panda::guard::ObjectProperty::Update()
49 {
50     auto &literalArrayTable = this->program_->prog_->literalarray_table;
51     PANDA_GUARD_ASSERT_PRINT(literalArrayTable.find(this->literalArrayIdx_) == literalArrayTable.end(), TAG,
52                              ErrorCode::GENERIC_ERROR, "get bad literalArrayIdx:" << this->literalArrayIdx_);
53 
54     auto &literalArray = literalArrayTable.at(this->literalArrayIdx_);
55     if (this->contentNeedUpdate_) {
56         this->obfName_ = GuardContext::GetInstance()->GetNameMapping()->GetName(this->name_);
57         LOG(INFO, PANDAGUARD) << TAG << "obfName:" << this->obfName_;
58         literalArray.literals_[this->index_].value_ = this->obfName_;
59     }
60 
61     if (this->method_) {
62         this->method_->Obfuscate();
63         literalArray.literals_[this->index_ + LITERAL_OBJECT_ITEM_LEN].value_ = this->method_->obfIdx_;
64     }
65 }
66 
SetContentNeedUpdate(bool toUpdate)67 void panda::guard::ObjectProperty::SetContentNeedUpdate(bool toUpdate)
68 {
69     this->contentNeedUpdate_ = toUpdate && this->needUpdate_;
70     this->needUpdate_ = true;
71 
72     if (this->method_) {
73         this->method_->SetContentNeedUpdate(toUpdate);
74     }
75 }
76 
SetExportAndRefreshNeedUpdate(bool isExport)77 void panda::guard::ObjectProperty::SetExportAndRefreshNeedUpdate(bool isExport)
78 {
79     if (this->method_) {
80         this->method_->SetExportAndRefreshNeedUpdate(isExport);
81     }
82 
83     Entity::SetExportAndRefreshNeedUpdate(isExport);
84 }
85 
Build()86 void panda::guard::Object::Build()
87 {
88     LOG(INFO, PANDAGUARD) << TAG << "object create for " << this->literalArrayIdx_ << " start";
89 
90     const auto &literalArray = this->program_->prog_->literalarray_table.at(this->literalArrayIdx_);
91     size_t keyIndex = 1;                                     // object item key index
92     size_t valueIndex = keyIndex + LITERAL_OBJECT_ITEM_LEN;  // object item value index
93     while (valueIndex < literalArray.literals_.size()) {
94         auto &valueLiteral = literalArray.literals_[valueIndex];
95         const bool isMethod = valueLiteral.tag_ == panda_file::LiteralTag::METHOD;
96         CreateProperty(literalArray, keyIndex, isMethod);
97         if (isMethod) {
98             keyIndex += LITERAL_OBJECT_METHOD_ITEM_GROUP_LEN;
99         } else {
100             keyIndex += LITERAL_OBJECT_COMMON_ITEM_GROUP_LEN;
101         }
102         valueIndex = keyIndex + LITERAL_OBJECT_ITEM_LEN;
103     }
104     LOG(INFO, PANDAGUARD) << TAG << "object create for " << this->literalArrayIdx_ << " end";
105 }
106 
CreateProperty(const pandasm::LiteralArray & literalArray,size_t index,bool isMethod)107 void panda::guard::Object::CreateProperty(const pandasm::LiteralArray &literalArray, size_t index, bool isMethod)
108 {
109     const auto &[keyTag, keyValue] = literalArray.literals_[index];
110     PANDA_GUARD_ASSERT_PRINT(keyTag != panda_file::LiteralTag::STRING, TAG, ErrorCode::GENERIC_ERROR,
111                              "bad keyTag literal tag");
112 
113     const auto property = std::make_shared<ObjectProperty>(this->program_, this->literalArrayIdx_);
114     property->name_ = StringUtil::UnicodeEscape(std::get<std::string>(keyValue));
115     property->scope_ = this->scope_;
116     property->export_ = this->export_;
117     property->index_ = index;
118 
119     if (isMethod) {
120         const size_t valueLiteralIndex = index + 2;
121         PANDA_GUARD_ASSERT_PRINT(valueLiteralIndex >= literalArray.literals_.size(), TAG, ErrorCode::GENERIC_ERROR,
122                                  "bad valueLiteralIndex:" << valueLiteralIndex);
123         const auto &[valueTag, valueValue] = literalArray.literals_[valueLiteralIndex];
124         PANDA_GUARD_ASSERT_PRINT(valueTag != panda_file::LiteralTag::METHOD, TAG, ErrorCode::GENERIC_ERROR,
125                                  "bad valueLiteral tag:" << (int)valueTag);
126         property->method_ = std::make_shared<PropertyMethod>(this->program_, std::get<std::string>(valueValue));
127         property->method_->node_ = this->node_;
128         property->method_->export_ = this->export_;
129         property->method_->scope_ = this->scope_;
130     }
131 
132     property->Create();
133 
134     LOG(INFO, PANDAGUARD) << TAG << "find object property:" << property->name_;
135 
136     this->properties_.push_back(property);
137 }
138 
UpdateLiteralArrayIdx()139 void panda::guard::Object::UpdateLiteralArrayIdx()
140 {
141     if (!GuardContext::GetInstance()->GetGuardOptions()->IsFileNameObfEnabled()) {
142         return;
143     }
144 
145     const auto &it = this->program_->nodeTable_.find(this->recordName_);
146     PANDA_GUARD_ASSERT_PRINT(it == this->program_->nodeTable_.end(), TAG, ErrorCode::GENERIC_ERROR,
147                              "not find node: " + this->recordName_);
148     const auto &node = it->second;
149     if (node->name_ == node->obfName_) {
150         return;
151     }
152     std::string updatedLiteralArrayIdx = this->literalArrayIdx_;
153     updatedLiteralArrayIdx.replace(updatedLiteralArrayIdx.find(node->name_), node->name_.size(), node->obfName_);
154 
155     UpdateLiteralArrayTableIdx(this->literalArrayIdx_, updatedLiteralArrayIdx);
156 
157     this->literalArrayIdx_ = updatedLiteralArrayIdx;
158 
159     for (auto &inst : this->defineInsList_) {
160         inst.ins_->GetId(INDEX_0) = updatedLiteralArrayIdx;
161     }
162 
163     for (auto &property : this->properties_) {
164         property->literalArrayIdx_ = updatedLiteralArrayIdx;
165     }
166 }
167 
EnumerateMethods(const std::function<FunctionTraver> & callback)168 void panda::guard::Object::EnumerateMethods(const std::function<FunctionTraver> &callback)
169 {
170     for (const auto &property : this->properties_) {
171         if (property->method_) {
172             callback(property->method_.operator*());
173         }
174     }
175 
176     for (auto &method : this->outerMethods_) {
177         callback(*method);
178     }
179 }
180 
ExtractNames(std::set<std::string> & strings) const181 void panda::guard::Object::ExtractNames(std::set<std::string> &strings) const
182 {
183     for (const auto &property : this->properties_) {
184         property->ExtractNames(strings);
185     }
186 
187     for (const auto &property : this->outerProperties_) {
188         property->ExtractNames(strings);
189     }
190 
191     for (const auto &method : this->outerMethods_) {
192         method->ExtractNames(strings);
193     }
194 }
195 
RefreshNeedUpdate()196 void panda::guard::Object::RefreshNeedUpdate()
197 {
198     this->needUpdate_ = true;
199     this->needUpdateName_ = TopLevelOptionEntity::NeedUpdate(*this);
200 }
201 
Update()202 void panda::guard::Object::Update()
203 {
204     LOG(INFO, PANDAGUARD) << TAG << "object update for " << this->literalArrayIdx_ << " start";
205 
206     if (this->contentNeedUpdate_ && this->needUpdateName_ && !this->name_.empty()) {
207         this->obfName_ = GuardContext::GetInstance()->GetNameMapping()->GetName(this->name_);
208     }
209 
210     UpdateLiteralArrayIdx();
211 
212     for (const auto &property : this->properties_) {
213         property->Obfuscate();
214     }
215 
216     for (const auto &property : this->outerProperties_) {
217         property->Obfuscate();
218     }
219 
220     for (const auto &method : this->outerMethods_) {
221         method->Obfuscate();
222     }
223 
224     LOG(INFO, PANDAGUARD) << TAG << "object update for " << this->literalArrayIdx_ << " end";
225 }
226 
WriteNameCache(const std::string & filePath)227 void panda::guard::Object::WriteNameCache(const std::string &filePath)
228 {
229     if (!this->obfuscated_ || !this->contentNeedUpdate_) {
230         return;
231     }
232 
233     if (this->needUpdateName_ && !this->obfName_.empty()) {
234         GuardContext::GetInstance()->GetNameCache()->AddObfIdentifierName(filePath, this->GetNameCacheScope(),
235                                                                           this->obfName_);
236     }
237 
238     for (const auto &property : this->properties_) {
239         property->WriteNameCache(filePath);
240     }
241 
242     for (const auto &property : this->outerProperties_) {
243         property->WriteNameCache(filePath);
244     }
245 }
246 
SetContentNeedUpdate(bool toUpdate)247 void panda::guard::Object::SetContentNeedUpdate(bool toUpdate)
248 {
249     this->contentNeedUpdate_ = toUpdate;
250     for (const auto &property : this->properties_) {
251         property->SetContentNeedUpdate(toUpdate);
252     }
253     for (const auto &method : this->outerMethods_) {
254         method->SetContentNeedUpdate(toUpdate);
255     }
256 }
257 
SetExportAndRefreshNeedUpdate(bool isExport)258 void panda::guard::Object::SetExportAndRefreshNeedUpdate(bool isExport)
259 {
260     for (const auto &property : this->properties_) {
261         property->SetExportAndRefreshNeedUpdate(isExport);
262     }
263 
264     for (const auto &property : this->outerProperties_) {
265         property->SetExportAndRefreshNeedUpdate(isExport);
266     }
267 
268     for (const auto &method : this->outerMethods_) {
269         method->SetExportAndRefreshNeedUpdate(isExport);
270     }
271 
272     Entity::SetExportAndRefreshNeedUpdate(isExport);
273 }
274 
SetExportName(const std::string & exportName)275 void panda::guard::Object::SetExportName(const std::string &exportName)
276 {
277     this->name_ = exportName;
278     this->obfName_ = exportName;
279     this->SetNameCacheScope(exportName);
280 }
281