news 2026/4/15 2:59:29

PicoCTF writeup - picoMini —— Pico Bank

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PicoCTF writeup - picoMini —— Pico Bank

Today, We will begin the hardest part of the picoMini writeup——Pico Bank.

Now look at the question


and the hints.



I choose android-killer to inspect the apk.(you can also use other app like apktool or jadxGUI)


Open the pico-bank app in Mumu simulator.

before we login, we must know the password.

Try to find it in the source code!


search "login"


we can see the login.smali.

Click it.


We can find the username and password in the login$1.smali


Login now.

username:johnson password:tricky1990

And we can see this.

Then we need to find the OTP value.


Try to search the OTP.


Find it! So easy.

The otp is 9673


Here is the page after we login.


Look at the notification.

It seems that we need to check the server's responce , so we have to enter the otp again😭.


And we need to investigate the history data.

It looks like binary code, because it is composed of 0 and 1.


Try to write down all the numbers.

1110000 1101001 1100011 1101111 1000011 1010100 1000110 1111011 110001 1011111 1101100 110001 110011 1100100 1011111 110100 1100010 110000 1110101 1110100 1011111 1100010 110011 110001 1101110 1100111 1011111

Throw it to Deepseek,let AI to transfer the binary code into ASCII.


so the first part of the flag is

picoCTF{1_l13d_4b0ut_b31ng_

OK. Now ,we need to find another part of it.

FIRST,try to get some hint in the source code.

We need to find out how the server handle the responce.

# annotations .annotation system Ldalvik/annotation/EnclosingMethod; value = Lcom/example/picobank/OTP;->verifyOtp(Ljava/lang/String;)V .end annotation .annotation system Ldalvik/annotation/InnerClass; accessFlags = 0x0 name = null .end annotation .annotation system Ldalvik/annotation/Signature; value = { "Ljava/lang/Object;", "Lcom/android/volley/Response$Listener<", "Lorg/json/JSONObject;", ">;" } .end annotation # instance fields .field final synthetic this$0:Lcom/example/picobank/OTP; # direct methods .method constructor <init>(Lcom/example/picobank/OTP;)V .locals 0 .param p1, "this$0" # Lcom/example/picobank/OTP; .line 86 iput-object p1, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method .method public onResponse(Lorg/json/JSONObject;)V .locals 8 .param p1, "response" # Lorg/json/JSONObject; .line 90 const-string v0, "hint" const-string v1, "flag" :try_start_0 const-string v2, "success" invoke-virtual {p1, v2}, Lorg/json/JSONObject;->getBoolean(Ljava/lang/String;)Z move-result v2 .line 91 .local v2, "success":Z if-eqz v2, :cond_0 .line 92 invoke-virtual {p1, v1}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String; move-result-object v3 .line 93 .local v3, "flag":Ljava/lang/String; invoke-virtual {p1, v0}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String; move-result-object v4 .line 95 .local v4, "hint":Ljava/lang/String; new-instance v5, Landroid/content/Intent; iget-object v6, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; const-class v7, Lcom/example/picobank/MainActivity; invoke-direct {v5, v6, v7}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V .line 96 .local v5, "intent":Landroid/content/Intent; invoke-virtual {v5, v1, v3}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent; .line 97 invoke-virtual {v5, v0, v4}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent; .line 98 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-virtual {v0, v5}, Lcom/example/picobank/OTP;->startActivity(Landroid/content/Intent;)V .line 99 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-virtual {v0}, Lcom/example/picobank/OTP;->finish()V .line 100 .end local v3 # "flag":Ljava/lang/String; .end local v4 # "hint":Ljava/lang/String; .end local v5 # "intent":Landroid/content/Intent; goto :goto_0 .line 101 :cond_0 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; const-string v1, "Invalid OTP"

We know that, the otp_value was firstly passed to VERIFYOTP , then, if the value is correct ,we can see the flag.

Try search the verifyotp

.method private verifyOtp(Ljava/lang/String;)V .locals 10 .param p1, "otp" # Ljava/lang/String; .line 67 const-string v0, "your server url" .line 68 .local v0, "severUrl":Ljava/lang/String; new-instance v1, Ljava/lang/StringBuilder; invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 const-string v2, "/verify-otp" invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v1 .line 70 .local v1, "endpoint":Ljava/lang/String; invoke-virtual {p0}, Lcom/example/picobank/OTP;->getResources()Landroid/content/res/Resources; move-result-object v2 sget v3, Lcom/example/picobank/R$string;->otp_value:I invoke-virtual {v2, v3}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String; move-result-object v2 invoke-virtual {v2, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z move-result v2 if-eqz v2, :cond_0 .line 71 new-instance v2, Landroid/content/Intent; const-class v3, Lcom/example/picobank/MainActivity; invoke-direct {v2, p0, v3}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V .line 72 .local v2, "intent":Landroid/content/Intent; invoke-virtual {p0, v2}, Lcom/example/picobank/OTP;->startActivity(Landroid/content/Intent;)V .line 73 invoke-virtual {p0}, Lcom/example/picobank/OTP;->finish()V .line 74 .end local v2 # "intent":Landroid/content/Intent; goto :goto_0 .line 75 :cond_0 const-string v2, "Invalid OTP"

Here in the code , our server url is connected with the "/verify-otp".

like this.


And then we need to POST the otpvalue to server .

Use burpsuite.


Don't forget to add the Content-type , otherwise it will fail.


Here is the response.


So the second part of the flag is

s3cur3d_m0b1l3_l0g1n_e9d3786f}

OK! Still so easy today!🥳See you!

flag

picoCTF{1_l13d_4b0ut_b31ng_s3cur3d_m0b1l3_l0g1n_e9d3786f}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 4:04:52

谷歌浏览器插件打包和加载

1.去插件管理页面 谷歌浏览器插件管理 edge插件管理&#xff0c;查看插件id 2.复制id &#xff0c;查找文件所在位置(注意替换插件id) find ~/Library -type d -name "bhghoamapcdpbohphigoooaddinpkbai" 2>/dev/null 3.复制插件所在位置&#xff0c;在插件管理…

作者头像 李华
网站建设 2026/4/7 23:35:16

Dify智能体平台的版本发布机制是如何运作的?

Dify智能体平台的版本发布机制是如何运作的&#xff1f; 在AI应用从实验原型迈向生产系统的今天&#xff0c;一个常被忽视但至关重要的问题浮出水面&#xff1a;我们如何确保今天调好的提示词&#xff0c;明天上线后依然有效&#xff1f; 这个问题背后&#xff0c;是传统AI开…

作者头像 李华
网站建设 2026/4/8 8:32:50

Stable Diffusion WebUI:DeepDanbooru动漫标签自动生成指南

Stable Diffusion WebUI 中的 DeepDanbooru 动漫标签自动化实践 在 AI 绘画领域&#xff0c;精准描述一幅复杂动漫画面始终是创作中的一大痛点。即便经验丰富的用户&#xff0c;也常因遗漏细节或表达模糊而影响出图质量。更别提批量生成时手动撰写 Prompt 的重复劳动——这不仅…

作者头像 李华
网站建设 2026/4/14 0:43:08

反汇编变量

反汇编变量 全局变量 全局变量和常量有着相似的性质&#xff0c;都是在程序执行之前就存在了。常量在PE的不可写数据节中&#xff0c;全局变量和局部变量在PE的可读可写数据节中。 下面来看一个简单的例子&#xff1a; #include <stdio.h>int g_num 0x12345678;int main…

作者头像 李华
网站建设 2026/4/14 9:44:46

30分钟上手动漫生成模型Counterfeit-V2.5

30分钟上手动漫生成模型Counterfeit-V2.5 在AI图像生成的浪潮中&#xff0c;二次元风格内容正以前所未有的速度占领创作者的视野。从独立画师到游戏美术团队&#xff0c;越来越多的人希望借助深度学习技术快速产出高质量、风格统一的动漫角色图。然而现实往往是&#xff1a;环…

作者头像 李华
网站建设 2026/4/7 10:00:24

BioSIM 人TNK-tPA(SIM0359):保证最终产物的高纯度与高活性

在现代生物医药研究中&#xff0c;生物类似药&#xff08;Biosimilars&#xff09;正逐渐成为创新药物的重要补充。它们不仅在成本控制上具有显著优势&#xff0c;同时在药效和安全性方面也展现出与原研药相当的潜力。作为这一领域的前沿探索者&#xff0c;InvivoCrown 推出的 …

作者头像 李华