news 2026/9/21 13:19:46

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/9/22 0:44:07

开源5G基站硬件参数

威武纪 高集成RFMC7000模块 SDR软件无线电 AD9371 FMC子卡和拓展卡pcie 300MHz~6GHz频段 SDR 开发评估发射接收卡 双通道收发链路 智邮开源 5G通信验证 射频板卡 OXG-SDR4100 软件无线电 SDR开发板 搭载两颗AD9371 开源5G基站OAI pcie 4路发射 4路接收 300MHz&#xff5e;6GHz …

作者头像 李华
网站建设 2026/9/22 1:27:06

C#开发桌面应用调用GPT-SoVITS REST API实战

C# 桌面应用集成 GPT-SoVITS 实现个性化语音合成实战 在当前 AI 技术快速落地的背景下&#xff0c;语音合成已不再是科研实验室里的“黑箱”技术。越来越多开发者希望将高质量的 TTS 能力嵌入到本地工具中——尤其是那些需要离线运行、保护隐私或具备图形化操作界面的应用场景。…

作者头像 李华
网站建设 2026/9/21 17:37:33

Dify Docker部署与使用全指南

Dify Docker部署与使用全指南 在生成式AI迅速渗透各行各业的今天&#xff0c;越来越多企业希望快速构建专属的智能应用——无论是自动回复客户咨询的客服机器人&#xff0c;还是能批量生成营销文案的内容引擎。但直接基于大模型从零开发&#xff0c;往往面临工程复杂、迭代缓慢…

作者头像 李华
网站建设 2026/9/22 11:32:34

数组作为参数

数组作为参数 当数组作为参数传递的时候&#xff0c;实际上传递的是数组的首地址&#xff0c;在语法上来说传递的是一个指针变量。 #include <stdio.h> #include <string.h>void getArrLen(char buffer[]) {printf_s("using sizeof: %zd\n", sizeof(buff…

作者头像 李华
网站建设 2026/9/21 15:30:59

蜜罐技术-德迅猎鹰

什么是蜜罐&#xff1f;蜜罐是一种主动防御技术&#xff0c;通过主动的暴露一些漏洞、设置一些诱饵来引诱攻击者进行攻击&#xff0c;从而可以对攻击行为进行捕获和分析。原理是什么&#xff1f;蜜罐可以故意暴露一些易受攻击的端口&#xff0c;使这些端口保持在开放状态&#…

作者头像 李华
网站建设 2026/9/21 23:28:43

Daily Report — Day 9 (Beta)

Daily Report — Day 9 (Beta)&#x1f4c5; 日期&#xff1a;2025/12/16&#x1f465; 参与人&#xff1a;zc、lzy、shr、zmj、xhy✅ 昨日完成工作&#xff08;Day 8 落地成果&#xff09;推荐模块稳定性修复&#xff08;zc&#xff09;对现有权重计算逻辑进行边界检查与异常兜…

作者头像 李华