news 2026/4/16 9:08:03

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/16 9:06:16

LobeChat能否接入Steam API?游戏玩家个性化助手

LobeChat能否接入Steam API&#xff1f;游戏玩家个性化助手 在如今这个AI无处不在的时代&#xff0c;我们早已不再满足于“能聊天”的智能助手。玩家想要的是一个懂自己游戏习惯、了解好友动态、甚至能在关键时刻提醒“你差最后一个成就了”的贴心伙伴。而LobeChat的出现&#…

作者头像 李华
网站建设 2026/4/16 9:07:47

百度指数观察:GPT-SoVITS关键词搜索趋势解读

GPT-SoVITS&#xff1a;从百度指数看语音克隆的平民化浪潮 在短视频博主开始为每条内容定制专属配音、独立游戏开发者尝试让NPC拥有“真人声线”的今天&#xff0c;一个技术名词悄然登上百度指数热搜榜——GPT-SoVITS。这个由中文社区推动、融合前沿架构的开源项目&#xff0c…

作者头像 李华
网站建设 2026/4/14 4:30:17

LobeChat能否设置会话过期时间?数据隐私保护机制

LobeChat 的会话过期控制与数据隐私保护机制 在企业级 AI 应用日益普及的今天&#xff0c;一个看似简单的功能——“会话是否自动过期”——背后往往牵动着安全、合规与用户体验的多重博弈。以开源聊天界面 LobeChat 为例&#xff0c;它凭借现代化的交互设计和灵活的模型接入能…

作者头像 李华
网站建设 2026/4/12 1:51:19

10分钟搞定算命运势测算站:PHP开源源码实战笔记

10分钟搞定算命运势测算站&#xff1a;PHP开源源码实战笔记写在前面&#xff1a; 本文不是鼓励封建迷信&#xff0c;而是程序员对“玄学系统”的一次白盒调试。 把《易经》里能“if/else”的部分抠出来&#xff0c;用150行PHP跑通&#xff0c;再扔进Docker&#xff0c;10分钟就…

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

Qwen-Image:突破文本与图像编辑的视觉生成新范式

Qwen-Image&#xff1a;重塑视觉生成的精准控制新范式 在广告设计、电商展示和出版编辑等实际场景中&#xff0c;一个长期困扰AIGC从业者的现实问题是&#xff1a;模型能“画出来”&#xff0c;但很难“按要求画对”。尤其是涉及中文文案的设计任务——“福”字少一横、“龍”字…

作者头像 李华