Skip to content

Commit cb195e7

Browse files
authored
Merge pull request #18 from RLakukolja/hotfix-1
Fix sample reputation override example
2 parents da746eb + c640d7c commit cb195e7

File tree

1 file changed

+85
-141
lines changed

1 file changed

+85
-141
lines changed

TitaniumCloud/sample_management.ipynb

Lines changed: 85 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"- **FileUpload** (*TCA-0202-0203 - File Upload*)\n",
2323
"- **FileDownload** (*TCA-0201 - File Download*)\n",
2424
"- **ReanalyzeFile** (*TCA-0205 - Re-Analyze File*)\n",
25+
"- **FileReputation** (*TCA-0101 - File Reputation (single query)*)\n",
26+
"- **FileReputationOverride** (*TCA-0102 - File Reputation Override*)\n",
2527
"- **DeleteFile** (*TCA-0204 - Delete File*)\n",
2628
"\n",
2729
"### Credentials\n",
@@ -41,16 +43,12 @@
4143
},
4244
{
4345
"cell_type": "code",
44-
"execution_count": 2,
45-
"metadata": {
46-
"ExecuteTime": {
47-
"end_time": "2024-06-24T13:00:18.771975493Z",
48-
"start_time": "2024-06-24T13:00:18.731201662Z"
49-
}
50-
},
46+
"execution_count": null,
47+
"metadata": {},
5148
"outputs": [],
5249
"source": [
53-
"from ReversingLabs.SDK.ticloud import FileUpload, FileDownload, ReanalyzeFile, DeleteFile"
50+
"from ReversingLabs.SDK.ticloud import FileUpload, FileDownload, ReanalyzeFile, DeleteFile, FileReputationUserOverride, FileReputation, calculate_hash\n",
51+
"from ReversingLabs.SDK.helper import SHA1, SHA256, MD5"
5452
]
5553
},
5654
{
@@ -66,13 +64,8 @@
6664
},
6765
{
6866
"cell_type": "code",
69-
"execution_count": 3,
70-
"metadata": {
71-
"ExecuteTime": {
72-
"end_time": "2024-06-24T13:00:25.846033807Z",
73-
"start_time": "2024-06-24T13:00:25.842115172Z"
74-
}
75-
},
67+
"execution_count": null,
68+
"metadata": {},
7669
"outputs": [],
7770
"source": [
7871
"import json\n",
@@ -99,24 +92,11 @@
9992
},
10093
{
10194
"cell_type": "code",
102-
"execution_count": 4,
103-
"metadata": {
104-
"ExecuteTime": {
105-
"end_time": "2024-06-24T13:01:24.894826465Z",
106-
"start_time": "2024-06-24T13:01:24.346445039Z"
107-
}
108-
},
109-
"outputs": [
110-
{
111-
"name": "stdout",
112-
"output_type": "stream",
113-
"text": [
114-
"200\n"
115-
]
116-
}
117-
],
95+
"execution_count": null,
96+
"metadata": {},
97+
"outputs": [],
11898
"source": [
119-
"FILE_NAME = \"file_name_placeholder\"\n",
99+
"FILE_NAME = \"README.md\"\n",
120100
"\n",
121101
"file_upload = FileUpload(\n",
122102
" host=\"https://data.reversinglabs.com\",\n",
@@ -125,10 +105,20 @@
125105
" user_agent=USER_AGENT\n",
126106
")\n",
127107
"\n",
108+
"with open(FILE_NAME, \"rb\") as sample:\n",
109+
" sample_md5 = calculate_hash(data_input=sample, hashing_algorithm=MD5)\n",
110+
" sample.seek(0)\n",
111+
" sample_sha1 = calculate_hash(data_input=sample, hashing_algorithm=SHA1)\n",
112+
" sample.seek(0)\n",
113+
" sample_sha256 = calculate_hash(data_input=sample, hashing_algorithm=SHA256)\n",
114+
"\n",
128115
"upload_response = file_upload.upload_sample_from_path(file_path=FILE_NAME)\n",
129116
"\n",
130117
"status_code = upload_response.status_code\n",
131-
"print(status_code)"
118+
"print(status_code)\n",
119+
"print(\"md5\", sample_md5)\n",
120+
"print(\"sha1\", sample_sha1)\n",
121+
"print(\"sha256\", sample_sha256)"
132122
]
133123
},
134124
{
@@ -154,7 +144,7 @@
154144
"metadata": {},
155145
"outputs": [],
156146
"source": [
157-
"FILE_HASH = \"sha1_hash_placeholder\"\n",
147+
"FILE_HASH = \"8e21cde3f269b7f359eb8903a130ab11e060325069e16c0ba1674c141d6c9d01\"\n",
158148
"\n",
159149
"file_download = FileDownload(\n",
160150
" host=\"https://data.reversinglabs.com\",\n",
@@ -188,22 +178,9 @@
188178
},
189179
{
190180
"cell_type": "code",
191-
"execution_count": 7,
192-
"metadata": {
193-
"ExecuteTime": {
194-
"end_time": "2024-06-24T13:15:51.128618407Z",
195-
"start_time": "2024-06-24T13:15:51.049367153Z"
196-
}
197-
},
198-
"outputs": [
199-
{
200-
"name": "stdout",
201-
"output_type": "stream",
202-
"text": [
203-
"Sample sent for rescanning\n"
204-
]
205-
}
206-
],
181+
"execution_count": null,
182+
"metadata": {},
183+
"outputs": [],
207184
"source": [
208185
"reanalyze = ReanalyzeFile(\n",
209186
" host=\"https://data.reversinglabs.com\",\n",
@@ -228,9 +205,9 @@
228205
"`Sample sent for rescanning`\n",
229206
"\n",
230207
"\n",
231-
"### 6. Delete file\n",
232-
"In case we no longer want a file to be present in the cloud and available for analysis or download, we can delete it.\n",
233-
"To delete a file from the TitaniumCloud, we will use the `DeleteFile` class."
208+
"### 6. Sample reputation override\n",
209+
"In case we wish to override the classification provided to a sample by Titanium Cloud we can use the FileReputationUserOverride class to do so.\n",
210+
"But before we do that let's see if our sample already has an override on its classification."
234211
]
235212
},
236213
{
@@ -239,17 +216,12 @@
239216
"metadata": {},
240217
"outputs": [],
241218
"source": [
242-
"delete_file = DeleteFile(\n",
219+
"file_reputation_override = FileReputationUserOverride(\n",
243220
" host=\"https://data.reversinglabs.com\",\n",
244221
" username=USERNAME,\n",
245222
" password=PASSWORD,\n",
246223
" user_agent=USER_AGENT\n",
247-
")\n",
248-
"\n",
249-
"delete_response = delete_file.delete_samples(sample_hashes=FILE_HASH)\n",
250-
"\n",
251-
"response_text = delete_response.text\n",
252-
"print(response_text)"
224+
")"
253225
]
254226
},
255227
{
@@ -258,158 +230,126 @@
258230
"collapsed": false
259231
},
260232
"source": [
261-
"Again, we used the same file hash. If our file deletion request was successful, the response text will have a non-empty list called `deleted_hashes`. This list carries the hashes of files that have successfully been deleted with this request."
233+
"We do this by requesting a collection of all sample hashes of a specific hash type.\n",
234+
"In this example we use the SHA256 algorithm.\n",
235+
"We check the first page to see if our sample is present."
262236
]
263237
},
264238
{
265239
"cell_type": "code",
266-
"execution_count": null,
267240
"outputs": [],
268241
"source": [
269242
"file_override_response = file_reputation_override.list_active_overrides(\"sha256\")\n",
270-
"print(file_override_response.text)\n",
243+
"count = len(file_override_response.json()[\"rl\"][\"user_override\"][\"hash_values\"])\n",
244+
"has_more = \"more\" if file_override_response.json()[\"rl\"][\"user_override\"].get(\"has_next\") else \"no more\"\n",
245+
"print(f\"Found {count} samples with overridden classification, there are {has_more} such samples\")\n",
271246
"is_in = \"in\" if file_override_response.text.find(sample_sha256) != -1 else \"not in\"\n",
272-
"print(\"\")\n",
273247
"print(f\"Sample is {is_in} the returned response page\")"
274248
],
275249
"metadata": {
276250
"collapsed": false
277-
}
251+
},
252+
"execution_count": null
278253
},
279254
{
280255
"cell_type": "markdown",
281256
"source": [
282-
"Cleaning up the override classification is easy. We do it using the same method as before."
257+
"Now we will add override the reputation to be malicious.\n",
258+
"We will then retrieve it from TiCloud and see how our change affects the output."
283259
],
284260
"metadata": {
285261
"collapsed": false
286262
}
287263
},
288264
{
289265
"cell_type": "code",
290-
"execution_count": null,
291266
"outputs": [],
292267
"source": [
293-
"cleanup_response = file_reputation_override.override_classification(\n",
294-
" remove_override=[\n",
295-
" {\n",
296-
" \"md5\": sample_md5,\n",
297-
" \"sha1\": sample_sha1,\n",
298-
" \"sha256\": sample_sha256\n",
299-
" }\n",
300-
" ]\n",
268+
"file_reputation_override_response = file_reputation_override.override_classification(\n",
269+
" override_samples=[{\n",
270+
" \"md5\": sample_md5,\n",
271+
" \"sha1\": sample_sha1,\n",
272+
" \"sha256\": sample_sha256,\n",
273+
" \"status\": \"MALICIOUS\"\n",
274+
" }]\n",
301275
")\n",
302-
"print(cleanup_response.status_code)\n",
303-
"print(cleanup_response.text)"
276+
"print(file_reputation_override_response.status_code)\n",
277+
"print(json.dumps(file_reputation_override_response.json(), indent=1))"
304278
],
305279
"metadata": {
306280
"collapsed": false
307-
}
281+
},
282+
"execution_count": null
308283
},
309284
{
310285
"cell_type": "markdown",
311286
"source": [
312-
"### 7. Delete file\n",
313-
"In case we no longer want a file to be present in the cloud and available for analysis or download, we can delete it.\n",
314-
"To delete a file from the TitaniumCloud, we will use the `DeleteFile` class."
287+
"You might need to give TiCloud a moment to propagate the new classification through the system."
315288
],
316289
"metadata": {
317290
"collapsed": false
318291
}
319292
},
320293
{
321294
"cell_type": "code",
322-
"execution_count": null,
323295
"outputs": [],
324296
"source": [
325-
"delete_file = DeleteFile(\n",
297+
"file_reputation = FileReputation(\n",
326298
" host=\"https://data.reversinglabs.com\",\n",
327299
" username=USERNAME,\n",
328300
" password=PASSWORD,\n",
329-
" user_agent=USER_AGENT\n",
301+
" user_agent=USER_AGENT \n",
330302
")\n",
331-
"\n",
332-
"delete_response = delete_file.delete_samples(sample_hashes=FILE_HASH)\n",
333-
"\n",
334-
"response_text = delete_response.text\n",
335-
"print(response_text)"
303+
"reputation_response = file_reputation.get_file_reputation(sample_sha256)\n",
304+
"print(reputation_response.status_code)\n",
305+
"print(json.dumps(reputation_response.json(), indent=1))"
336306
],
337307
"metadata": {
338308
"collapsed": false
339-
}
309+
},
310+
"execution_count": null
340311
},
341312
{
342-
"cell_type": "raw",
313+
"cell_type": "markdown",
343314
"source": [
344-
"Again, we used the same file hash. If our file deletion request was successful, the response text will have a non-empty list called `deleted_hashes`. This list carries the hashes of files that have successfully been deleted with this request."
315+
"Cleaning up the classification override is easy. We do it using the same method as before."
345316
],
346317
"metadata": {
347318
"collapsed": false
348319
}
349320
},
350321
{
351322
"cell_type": "code",
352-
"execution_count": null,
353-
"metadata": {},
354-
"outputs": [],
355-
"source": [
356-
"file_override_response = file_reputation_override.list_active_overrides(\"sha256\")\n",
357-
"print(file_override_response.text)\n",
358-
"is_in = \"in\" if file_override_response.text.find(sample_sha256) != -1 else \"not in\"\n",
359-
"print(\"\")\n",
360-
"print(f\"Sample is {is_in} the returned response page\")"
361-
]
362-
},
363-
{
364-
"cell_type": "markdown",
365-
"metadata": {
366-
"collapsed": false
367-
},
368-
"source": [
369-
"Cleaning up the override classification is easy. We do it using the same method as before."
370-
]
371-
},
372-
{
373-
"cell_type": "code",
374-
"execution_count": null,
375-
"metadata": {},
376323
"outputs": [],
377324
"source": [
378325
"cleanup_response = file_reputation_override.override_classification(\n",
379-
" remove_override=[\n",
380-
" {\n",
381-
" \"md5\": sample_md5,\n",
382-
" \"sha1\": sample_sha1,\n",
383-
" \"sha256\": sample_sha256\n",
384-
" }\n",
385-
" ]\n",
326+
" remove_override=[{\n",
327+
" \"md5\": sample_md5,\n",
328+
" \"sha1\": sample_sha1,\n",
329+
" \"sha256\": sample_sha256\n",
330+
" }]\n",
386331
")\n",
387332
"print(cleanup_response.status_code)\n",
388-
"print(cleanup_response.text)"
389-
]
390-
},
391-
{
392-
"cell_type": "markdown",
393-
"source": [],
333+
"print(json.dumps(cleanup_response.json(), indent=1))"
334+
],
394335
"metadata": {
395336
"collapsed": false
396-
}
337+
},
338+
"execution_count": null
397339
},
398340
{
399341
"cell_type": "markdown",
400-
"metadata": {
401-
"collapsed": false
402-
},
403342
"source": [
404343
"### 7. Delete file\n",
405344
"In case we no longer want a file to be present in the cloud and available for analysis or download, we can delete it.\n",
406345
"To delete a file from the TitaniumCloud, we will use the `DeleteFile` class."
407-
]
346+
],
347+
"metadata": {
348+
"collapsed": false
349+
}
408350
},
409351
{
410352
"cell_type": "code",
411-
"execution_count": null,
412-
"metadata": {},
413353
"outputs": [],
414354
"source": [
415355
"delete_file = DeleteFile(\n",
@@ -423,16 +363,20 @@
423363
"\n",
424364
"response_text = delete_response.text\n",
425365
"print(response_text)"
426-
]
427-
},
428-
{
429-
"cell_type": "raw",
366+
],
430367
"metadata": {
431368
"collapsed": false
432369
},
370+
"execution_count": null
371+
},
372+
{
373+
"cell_type": "raw",
433374
"source": [
434375
"Again, we used the same file hash. If our file deletion request was successful, the response text will have a non-empty list called `deleted_hashes`. This list carries the hashes of files that have successfully been deleted with this request."
435-
]
376+
],
377+
"metadata": {
378+
"collapsed": false
379+
}
436380
}
437381
],
438382
"metadata": {

0 commit comments

Comments
 (0)